What's Changed
Repeating items are no longer mistaken for duplicates (#124)
OmniFocus keeps every completed occurrence of a repeating item as its own row, carrying the same name and the same repetition rule as the live one. A query with includeCompleted: true therefore returned rows that were indistinguishable from duplicates — and mutating one cascades through the live repeat chain. In one real incident, eight targeted changes produced roughly fifteen dropped rows, including a future occurrence of a daily task.
query_omnifocusnow returnsisPastOccurrence(included by default) and labels those rows in its output:⟲ past occurrence — not a duplicate.edit_itemandremove_itemrefuse to mutate a past occurrence, explaining why. PassallowPastOccurrence: truefor the rare case where you genuinely mean the historical row.
Completing or editing the live occurrence is unaffected — that is the normal way repeats work and it continues to behave exactly as before. Note the check is on repeating item plus terminal status, not on the shape of the id: a repeating project's live identifier is itself dotted (abc.116 can be the active project while abc.116.43 is history), so rejecting dotted ids would have made repeating projects uneditable.
Clients survive a daemon restart (#123)
If the shared daemon died while clients were attached — a crash, or a manual kill during troubleshooting — every attached client lost its OmniFocus tools for the rest of its session. The shim exited on the assumption the client would relaunch; clients that treat a stdio server exit as terminal do not. One long-running session lost the tools for a week without noticing.
The shim now reconnects, replays the client's initialize handshake so the new daemon's session matches what the client still believes, and returns retryable errors for any requests that were in flight when the connection dropped rather than leaving the client waiting on responses that no longer exist. Bounded to five reconnects, after which it exits as before.
Note that a write interrupted mid-flight may have partially applied — re-query before retrying a write, rather than assuming it did not land.
Full Changelog: v1.14.1...v1.15.0