fix(imessage): resume watch from catchup cursor#79085
fix(imessage): resume watch from catchup cursor#79085CaptainTimon wants to merge 1 commit intoopenclaw:mainfrom
Conversation
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: no. high-confidence live reproduction path was established. Source inspection does show current main subscribes live-only with no persisted cursor path, and upstream imsg docs confirm the exclusive Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Land an iMessage-owned bounded catchup implementation after cursor writes are serialized and covered for concurrent updates, with live macOS/imsg restart replay proof and maintainer-approved defaults. Do we have a high-confidence way to reproduce the issue? No high-confidence live reproduction path was established. Source inspection does show current main subscribes live-only with no persisted cursor path, and upstream imsg docs confirm the exclusive Is this the best way to solve the issue? No, not merge-ready as proposed. The owner boundary and dependency contract are reasonable, but the cursor store needs concurrency-safe updates and the external PR needs real macOS/imsg restart replay proof. Full review comments:
Overall correctness: patch is incorrect What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 56fe64e8e369. |
Summary
chat.dbwhile OpenClaw was down were not replayed.imsgrowid per iMessage account and passes a boundedsince_rowid+startcursor towatch.subscribeon restart.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Real behavior proof (required for external PRs)
imsg rpcwatch.subscribefrom a persisted, exclusive rowid cursor instead of launching live-only after every Gateway restart.imsgJSON-RPC docs forwatch.subscribeparams (since_rowid,start,attachments).node --import tsx - <<'EOF' ... buildIMessageWatchSubscribeParams(...) ... EOFsince_rowid: 9000plus a 30-minute bounded ISOstart, which is the documentedimsg rpcreplay cursor contract.chat.dbwas not run from this Linux workspace.watch.subscribewith onlyattachments, soimsgstarted at the newest message and skipped rows written before launch.Root Cause (if applicable)
imsg watch.subscribeas a live-only stream and did not persist or pass the last processed message rowid across monitor restarts.imsgstarts at newest message whensince_rowidis omitted, by design.Regression Test Plan (if applicable)
extensions/imessage/src/monitor/catchup-cursor.test.ts,extensions/imessage/src/monitor.watch-subscribe-retry.test.ts,extensions/imessage/src/config-schema.test.tswatch.subscribe; validatecatchup.maxAgeMinutesschema bounds.imsgRPC cursor contract without needing a real macOS Messages database in unit CI.User-visible / Behavior Changes
$OPENCLAW_STATE_DIR/imessage/catchup-cursors.jsonafter processing live messages.channels.imessage.catchup.enabledandchannels.imessage.catchup.maxAgeMinutes(default enabled, 24 hours).Diagram (if applicable)
Security Impact (required)
No)No)No)No)No)Yes, explain risk + mitigation: N/A.Repro + Verification
Environment
imsg rpcchannels.imessage.catchup.maxAgeMinutes=30in unit coverageSteps
mainwith rowid9000.imsg rpcclient.watch.subscribeparams.Expected
since_rowid: 9000, a bounded ISOstart, and the existingattachmentsflag.Actual
extensions/imessage/src/monitor.watch-subscribe-retry.test.tsand the real module console output above.Evidence
Validation run:
Additional note:
Human Verification (required)
What you personally verified (not just CI), and how:
maxAgeMinutes: 0is rejected; lower rowid does not move the cursor backward.chat.dbfrom this Linux workspace.Review Conversations
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
Yes)Yes)No)channels.imessage.catchup.enabled/maxAgeMinutes.Risks and Mitigations
catchup.maxAgeMinutesand defaults to 24 hours; first run stays live-only until OpenClaw has processed and persisted a cursor.