Skip to content

fix(imessage): catch delayed reflected echoes#59980

Closed
neeravmakwana wants to merge 1 commit into
openclaw:mainfrom
neeravmakwana:fix/imessage-echo-dedup-reflections
Closed

fix(imessage): catch delayed reflected echoes#59980
neeravmakwana wants to merge 1 commit into
openclaw:mainfrom
neeravmakwana:fix/imessage-echo-dedup-reflections

Conversation

@neeravmakwana

Copy link
Copy Markdown
Contributor

Summary

  • Problem: iMessage reflected copies can miss dedupe when they arrive after the 4 second text fallback window or when the reflected text starts with replacement/control garbage.
  • Why it matters: missed echo suppression can re-ingest the assistant's own outbound reply as a fresh inbound message and create duplicate or looping replies.
  • What changed: extended the iMessage text fallback TTL to 30 seconds and normalized leading replacement/control characters in both the sent-message echo cache and the self-chat reflection cache.
  • What did NOT change (scope boundary): message ID matching, routing, outbound send behavior, and non-iMessage channels were not changed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause / Regression History (if applicable)

  • Root cause: extensions/imessage/src/monitor/echo-cache.ts only normalized CRLF plus trim and expired text fallback entries after 4 seconds, so delayed or prefix-corrupted reflected copies failed exact-text matching.
  • Missing detection / guardrail: coverage preserved the short TTL behavior instead of locking in delayed and corrupted-prefix echoes as dedupe cases.
  • Prior context (git blame, prior PR, issue, or refactor if known): existing iMessage echo-cache tests documented the 4 second text fallback assumption; the linked issue showed reflected text arriving 5 to 10 seconds later with leading U+FFFD characters.
  • Why this regressed now: the current iMessage reflection path can deliver slower or text-corrupted reflected copies than the original fallback assumptions allowed for.
  • If unknown, what was ruled out: ruled out a current fix in the active iMessage cache and inbound-processing paths; the issue behavior still reproduced against the current cache logic.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/imessage/src/monitor/monitor-provider.echo-cache.test.ts, extensions/imessage/src/monitor/self-chat-cache.test.ts, and extensions/imessage/src/monitor/self-chat-dedupe.test.ts.
  • Scenario the test should lock in: delayed 5 second reflections and reflected copies with leading replacement/control characters should still dedupe in both normal and self-chat flows.
  • Why this is the smallest reliable guardrail: the failure is inside the two normalization and TTL caches, so focused cache tests cover the bug directly without requiring live iMessage infrastructure.
  • Existing test that already covers this (if any): existing iMessage echo-cache tests covered the same caches but encoded the old 4 second miss behavior.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

  • iMessage now suppresses delayed reflected echoes for longer and also matches reflected copies whose text starts with replacement/control characters.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS 25.3.0
  • Runtime/container: pnpm workspace, Bun/Node repo defaults
  • Model/provider: N/A
  • Integration/channel (if any): iMessage
  • Relevant config (redacted): default test config

Steps

  1. Cache a recently sent iMessage text in the iMessage echo cache.
  2. Advance time by 5 seconds and query the cache with the same text, or with the same text prefixed by replacement/control characters.
  3. Observe whether the reflected copy is dropped as an echo.

Expected

  • Delayed reflected copies still match the text fallback window.
  • Leading replacement/control garbage does not break text dedupe.

Actual

  • Before this change, the 5 second text-only reflection missed the cache and prefix-corrupted text failed normalization.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: ran pnpm test -- extensions/imessage/src/monitor/monitor-provider.echo-cache.test.ts extensions/imessage/src/monitor/self-chat-cache.test.ts extensions/imessage/src/monitor/self-chat-dedupe.test.ts extensions/imessage/src/monitor/inbound-processing.test.ts; ran pnpm test:extension imessage; ran pnpm build; also sanity-checked the cache behavior directly before the fix and confirmed 5 second text-only and corrupted-prefix matches failed on the old logic.
  • Edge cases checked: self-chat dedupe uses the same normalization fix; message ID retention still outlives the shorter text fallback window.
  • What you did not verify: a live local iMessage roundtrip on macOS.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: a longer text fallback window could suppress a legitimate repeated identical text message if no message ID is available and it lands inside the same 30 second scope window.
    • Mitigation: the cache stays conversation-scoped, the longer-lived message ID path is unchanged, and the new normalization is limited to leading replacement/control garbage that should not be semantically meaningful for reflected copies.

Notes

  • pnpm check currently fails in unrelated pre-existing extensions/diffs/src/language-hints.test.ts type assertions on this tree; the iMessage-focused tests, extension lane, and pnpm build passed for this PR.
  • AI assistance: used an LLM coding agent for implementation and drafting, then reviewed the touched code paths and validation results before opening this PR.

Made with Cursor

@greptile-apps

greptile-apps Bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two related iMessage echo-suppression bugs: the text-fallback TTL in echo-cache.ts is extended from 4s to 30s to catch delayed reflected copies, and a normalization step is added to both echo-cache.ts and self-chat-cache.ts to strip leading C0 control characters and Unicode non-characters (U+FFFD, U+FFFE, U+FFFF, U+FEFF) before key comparison. The normalization is applied symmetrically in both remember and has, so there are no asymmetry issues, and the known trade-off (a repeated identical text message with no message ID could be suppressed within the 30s window) is explicitly acknowledged in the PR description and mitigated by the conversation-scoped key design.

Confidence Score: 5/5

Safe to merge — targeted, well-scoped fix with no P0/P1 findings and good test coverage of the new behavior.

All findings are P2 or below. The logic change is correct: normalization is symmetric (applied in both remember and has), the TTL extension is bounded by the conversation-scoped key, and the longer-lived message-ID path is untouched. Tests are updated to lock in the new TTL boundary and the corrupted-prefix matching behavior.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(imessage): catch delayed reflected e..." | Re-trigger Greptile

@neeravmakwana

Copy link
Copy Markdown
Contributor Author

I reviewed the current AI review surfaces on this PR before making any follow-up changes.

What I checked:

  • PR review threads via GraphQL
  • PR review comments via the pull-request review comment API
  • PR timeline items and bot comments
  • check-run annotations for the current head commit

Current result:

  • The only AI review content present right now is the Greptile summary comment.
  • There are no actionable inline review comments, no unresolved review threads, and no bot check annotations requesting a code change.
  • Greptile's current review is favorable and does not identify a correctness issue to fix.

Because there are no concrete AI review findings to act on, I did not make additional code changes just for the sake of churn.

Validation status for the current branch remains:

  • Focused iMessage regression tests passed
  • pnpm test:extension imessage passed
  • pnpm build passed
  • PR CI is green/pending in the expected lanes; the targeted iMessage lane is already passing

If another AI review tool posts specific findings later, I can address those directly in a follow-up update.

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

Labels

channel: imessage Channel integration: imessage size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iMessage DM echo: corrupted prefix breaks text-based dedup (v2026.3.31+)

1 participant