Skip to content

fix(helper): set message subject via IMMessageItem setSubject: on macOS 26 - #376

Merged
steipete merged 1 commit into
openclaw:mainfrom
webmasu:pr/macos26-subject
Nov 5, 2026
Merged

steipete merged 1 commit into
openclaw:mainfrom
webmasu:pr/macos26-subject

Conversation

@webmasu

@webmasu webmasu commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Problem

On macOS 26, IMMessageItem exposes the plain-string setSubject: setter and does not respond to setMessageSubject:. The helper therefore drops the subject on the item-construction path.

Change

Use setSubject: when available and retain the older attributed-string setter as fallback. The regression fixture mirrors the real item type and checks subjects on both the item and its wrapped message, including threaded replies.

make test-native-subjects runs a synthetic IMCore construction probe without resolving a chat or sending.

Native runtime evidence on macOS 26.6.2 (25G83)

Ran the same native probe against base 5af52a029b3d027cc064f16ead5ed60b888febfb and head 1c0826533704b0a3e3182de736f1ef56a7b4984b in the guest:

Scenario Base Head
No subject Pass Pass
Standalone subject Subject absent; fail Subject preserved on item and message; pass
Threaded subject Subject absent; fail Subject preserved on item and message; pass
Probe exit code 1 0

Both runs observed item_has_setSubject=true and item_has_setMessageSubject=false. Body and thread checks passed in every scenario. The test subject was the synthetic string Ämnesrad åäö ✅.

This is a newly executed native IMCore construction comparison, not a live send.

Validation

  • make test-helper: passes, including the subject and threaded-reply regressions.
  • make lint: Swift format and SwiftLint 0.65.1 pass with zero violations.
  • The shipping arm64 CLI and arm64e/arm64 helper build successfully and pass the macOS 14 deployment-target check.
  • The probe binaries were built with a macOS 14 minimum and run against macOS 26.6.2's actual IMCore.

Executed shipped send-path proof

The release CLI and helper from exact head 1c0826533704b0a3e3182de736f1ef56a7b4984b were staged separately, hash-checked and loaded into the real Messages process on macOS 26.6.2. Sent one standalone message and one reply to it, first between controlled numbers and then to a separate recipient's iPhone.

Actual command shapes, with recipient and body redacted:

"$HEAD/imsg" send-rich --chat 'any;-;<TEST_RECIPIENT>' --text '<UNIQUE_BODY_1>' --subject 'Test 4/5: Ämnesrad åäö ✅' --json
"$HEAD/imsg" send-rich --chat 'any;-;<TEST_RECIPIENT>' --text '<UNIQUE_BODY_2>' --subject 'Test 5/5: Ämnesrad i svar åäö ✅' --reply-to '<PARENT_GUID>' --json

Redacted terminal responses and read-only database observations for the separate-recipient run:

{
  "standalone": {
    "response": {
      "exit": 0,
      "stdout": {
        "queued": true,
        "id": "<MESSAGE_ROW>",
        "guid": "<MESSAGE_8>",
        "service": "iMessage",
        "chatGuid": "any;-;<REDACTED_NUMBER>",
        "message_id": "<MESSAGE_8>",
        "messageGuid": "<MESSAGE_8>",
        "chat_guid": "any;-;<REDACTED_NUMBER>"
      },
      "stderr": ""
    },
    "observed_outgoing_rows": [
      {
        "guid": "<MESSAGE_8>",
        "service": "iMessage",
        "is_from_me": 1,
        "is_sent": 1,
        "is_delivered": 1,
        "error": 0,
        "subject": "Test 4/5: Ämnesrad åäö ✅",
        "thread_originator_guid": null,
        "thread_originator_part": null,
        "balloon_bundle_id": null,
        "payload_bytes": null,
        "chat_service": "SMS"
      }
    ]
  },
  "threaded": {
    "response": {
      "exit": 0,
      "stdout": {
        "id": "<MESSAGE_ROW>",
        "message_id": "<MESSAGE_9>",
        "messageGuid": "<MESSAGE_9>",
        "queued": true,
        "chatGuid": "any;-;<REDACTED_NUMBER>",
        "service": "iMessage",
        "chat_guid": "any;-;<REDACTED_NUMBER>",
        "guid": "<MESSAGE_9>"
      },
      "stderr": ""
    },
    "observed_outgoing_rows": [
      {
        "guid": "<MESSAGE_9>",
        "service": "iMessage",
        "is_from_me": 1,
        "is_sent": 1,
        "is_delivered": 1,
        "error": 0,
        "subject": "Test 5/5: Ämnesrad i svar åäö ✅",
        "thread_originator_guid": "<MESSAGE_8>",
        "thread_originator_part": "0:0:77",
        "balloon_bundle_id": null,
        "payload_bytes": null,
        "chat_service": "SMS"
      }
    ]
  }
}

Both returned GUIDs resolved to outgoing iMessage rows with the exact requested subject, is_sent=1, is_delivered=1, and error=0. The reply's thread_originator_guid exactly equals the standalone message GUID. These are actual shipped-path sends through the real helper; the earlier base-fail/head-pass native construction comparison remains documented above.

Production was restored after testing. Personal identifiers, private paths, row IDs and message GUIDs are redacted; matching GUID placeholders retain the parent/reply relationship.

Recipient-side visual confirmation

The test operator has now confirmed that the subject lines display correctly on the receiving iPhone. This recipient-side visual confirmation supplements the recorded standalone/threaded send results and preserved subjects above. The parent/reply relationship remains independently verified by the database checks.

@clawsweeper

clawsweeper Bot commented Nov 1, 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 clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. labels Nov 1, 2026
@clawsweeper

clawsweeper Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex review: needs maintainer review before merge.

What this changes

The PR sets native message subjects through setSubject: while preserving the older setMessageSubject: fallback.

Example: Send a standalone message or threaded reply with subject “Ämnesrad åäö ✅” on macOS 26.

  • Before: The item-first constructor silently omits the requested subject.
  • After: The native item and wrapped message preserve the requested subject.

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) A focused repair of an existing capability, supported by native base/head comparison and exact-head shipped-send evidence, with no open findings.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): The exact-head release CLI and helper exercised applyItemExtendedFields through real send-rich standalone and threaded sends on macOS 26.6.2; redacted terminal and database output shows exact subjects, delivery acknowledgments, and the correct reply-parent relationship, satisfying the prior review's proof request without claiming recipient UI rendering.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: An explicitly supplied subject disappears from native text messages on macOS 26.
Reason: Subjects are an existing CLI and RPC capability, and every changed area supports restoring that contract.

Merge readiness

✅ Ready for maintainer review

Keep this PR open for landing: it fixes a subject-handling defect still present on main, with no actionable correctness findings.

Priority: P2
Reviewed head: 1c0826533704b0a3e3182de736f1ef56a7b4984b

Before merge

None.

Findings

None.

Agent review details

How this fits together

CLI and RPC requests pass subject text into the injected helper, which constructs native IMCore messages and dispatches them through Messages.

flowchart LR
  A[CLI or RPC request] --> B[Helper send handler]
  B --> C[Shared message builder]
  C --> D[Apply item subject]
  D --> E[Wrap native message]
  E --> F[Messages send]
Loading

Technical review

Best possible solution:

Land the focused repair in the existing item finalizer with its compatibility fallback and subject round-trip coverage.

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

Current-main source deterministically skips subject assignment when IMMessageItem exposes setSubject: without setMessageSubject:; the supplied native comparison reports base failure and head success on macOS 26.6.2, without an independent reviewer runtime run.

Is this the best way to solve the issue?

The patch repairs the shared construction owner directly, preserves older selector support, and uses the existing native-test pattern without introducing another sending path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 22b4da7d72d9.

Provenance checked

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Likely related people:

  • Peter Steinberger: Raw commit cb58dec adds Sources/IMsgHelper/MessageConstruction.inc:19 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: cb58dec17663; files: Sources/IMsgHelper/MessageConstruction.inc)
  • gennadyclaw: Raw commit 9ebd171 adds Tests/IMsgHelperTests/ThreadedReplyTests.m:135 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 9ebd171168c2; files: Tests/IMsgHelperTests/ThreadedReplyTests.m)

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient.
  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P2: An explicitly requested subject disappears in an advanced sending workflow while the message body and general sending capability remain available.
  • 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.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (1 earlier review cycle)
  • reviewed 2026-11-01T20:02:57.301Z sha 1c08265 :: needs real behavior proof before merge. :: none

Reviewed November 4, 2026, 6:30 AM ET / 11:30 UTC (Revision 2).

@webmasu

webmasu commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Updated the PR description with redacted executed terminal/database evidence for 1c08265.

Added actual standalone and threaded send-rich runs through the exact head helper on macOS 26.6.2, including a separate recipient. Both subjects persist exactly, both messages have delivery acknowledgments, and the reply stores the standalone message GUID as its parent. The PR body also retains the executed base-fail/head-pass native construction comparison.

The evidence excludes phone numbers and other private contact data.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:bug Preliminary submission classification; full source review pending. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. clawsweeper:intake:bug Preliminary submission classification; full source review pending. labels Nov 4, 2026
@webmasu

webmasu commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Recipient-side confirmation added to the PR description: The test operator has now confirmed that the subject lines display correctly on the receiving iPhone. This recipient-side visual confirmation supplements the recorded standalone/threaded send results and preserved subjects above. The parent/reply relationship remains independently verified by the database checks.

…OS 26

Preserve subjects on standalone messages and threaded replies with the current IMCore item setter (openclaw#376, thanks @webmasu).

Co-authored-by: webmasu <299281979+webmasu@users.noreply.github.com>
@steipete
steipete requested a review from a team as a code owner November 5, 2026 05:51
@steipete
steipete merged commit e02c71f into openclaw:main Nov 5, 2026
7 checks passed
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: 🦞 diamond lobster Very strong PR readiness with only minor 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.

2 participants