Skip to content

v2.0.2

Latest

Choose a tag to compare

@torsday torsday released this 11 Jun 14:13

2.0.2 (2026-06-10)

Summary — A large correctness patch (~70 fixes), no new API. The dominant theme is date & time handling: date filters, review-due windows, agenda and retrospective bounds, and bare-date parsing now compare instants and honour the local calendar day instead of mixing UTC components with ISO-string comparisons. Cache invalidation is tightened so cross-entity mutations (tags ↔ projects, subtask ↔ parent, convert-to-project) and limit-scoped list reads no longer serve stale pages. TaskPaper/OPML import-export round-trips faithfully — native @done/@dropped forms, note lines, and OPML attribute escaping. The OmniJS read/write path reaches parity with JXA (repetition parsing, task status, completed-by-children, convert-to-project, forecast tag, perspective restore), and the persistent transport gains UTF-8-safe framing, typed OF_UNSUPPORTED / JXA error-number surfacing, and cleaner restart handling. Webhooks, server-health reads (doctor, internal_status), recurrence-grammar parsing, and a changes_since watermark fix round it out. No API, schema, or wire-format changes — a safe drop-in upgrade from v2.0.1.

Fixed

  • adapter: align in-memory review-due window with jxa current-instant semantics (fbd8461)
  • adapter: compare in-memory date filters as timestamps, not strings (2293d6d)
  • adapter: default omitted completed filter to exclude in in-memory searchTasks (97778ed)
  • adapter: inherit parent's project for in-memory child create and move (000fc51)
  • adapter: route all jxa-routed mutators through the serial write queue (5738000)
  • cache: flush tag and folder list caches on cross-entity mutations (9d40b2b)
  • cache: flush the parent task scope when a subtask is mutated (ba5b7fb)
  • cache: flush the source project scope on task_convert_to_project (36c178b)
  • cache: flush the tag list cache on project mutations (7b2c7da)
  • cache: pass projectId on note and task-batch invalidation (0bdba1c)
  • capabilities: advertise the idempotency store's real ttl instead of a hard-coded 24h (f153a1b)
  • clarify: validate the choice before consuming the single-use replay token (0a37aec)
  • config: read OMNIFOCUS_LEGACY_TEXT_CONTENT in parseConfig so the parsed flag reflects the env (d442537)
  • describe: render preview dates in local time, not UTC components (a751485)
  • doctor: probe the live JXA bridge instead of the getLastSync cache read (9d61d4b)
  • domain: parse bare explicit-with-skip-weekends dates as local midnight (3ed505c)
  • envelope: do not report cap truncation when the lone item is kept whole (ca39f31)
  • export: dedupe project task tree fetch so subtasks export once (7dae1a5)
  • export: escape newlines, crs, and tabs in opml attribute values (713d35a)
  • export: import @dropped tasks via droptask instead of completetask (9b7c82b)
  • export: parse the native @done(date) form and honour its completion date (b9b750e)
  • export: require whitespace before the // note delimiter in taskpaper import (2fbd984)
  • export: round-trip note lines instead of phantom subtasks and silent loss (00b9d6c)
  • export: use local calendar day for taskpaper dates instead of utc (54dcbf8)
  • grammar: accept bare 'every {unit}' prose with implicit count of 1 (02c33cb)
  • grammar: keep weekday selection when an every-n-weeks interval is present (ebc7cc6)
  • grammar: map 'from the due date' to fixed and reserve due-again for completion phrasing (598a2ef)
  • jxa: clear project estimatedMinutes to null instead of writing 0 (0de28d4)
  • jxa: exclude undated tasks from task_list date filters (8d1767c)
  • jxa: never delete a directory passed as attachment destpath (e231df2)
  • jxa: omit monthlyAnchor for rrule positions outside the domain range (f2e1700)
  • jxa: read review interval as a bridged record and convert units to days (3c4fb5d)
  • observability: stop internal_status from hard-coding ofRunning: true (7f0fc97)
  • omnijs: derive blocked/available/dropped from taskStatus in perspective evaluation (131a91e)
  • omnijs: parse repetition from ruleString instead of nonexistent unit/steps (384fc26)
  • omnijs: persist the forecast tag via the settings store (3222ccd)
  • omnijs: resolve convert-to-project folders via flattenedFolders and insert at folder.ending (259e081)
  • omnijs: restore the user's window perspective after perspective evaluation (fbd7035)
  • omnijs: write completedByChildren on task create instead of jxa-only containsSingletonActions (50c91d9)
  • pagination: make null sort values cursor-stable in desc order (f8cc574)
  • parser: require a token boundary before the '//' note marker (b8321d8)
  • parser: warn on impossible calendar dates instead of rolling them over (7fd7c1e)
  • project: compare reviewDueBefore as instants instead of iso strings (0983f0b)
  • project: include limit in the project_list cache key (4f583fa)
  • resources: compute agenda day end with calendar math, not +24h (e421a3c)
  • resources: count completed tasks toward velocity weekly created totals (3ae8f5e)
  • resources: normalize retrospective window bounds to utc instants (026441d)
  • resources: parse bare agenda ?date as local midnight, not UTC (98f0051)
  • review: document null as reset-to-schedule for project_set_next_review_date (68c2c26)
  • review: exclude done and dropped projects from review_list_due (fe6c864)
  • review: use schema-valid example in set-next-review-date description (2a6fee7)
  • search: sort pages by code units to match the cursor predicate (ea73ea8)
  • server: derive the started manifest from canonical prompt and resource lists (050bb24)
  • server: exclude input and backpressure errors from the per-tool circuit count (06da7f1)
  • sync: stop changes_since from advancing the watermark past failed entity fetches (20c2fdf)
  • tag: use schema-valid trigger example in tag_set_location description (516a4f6)
  • task: compare updatedSince as instants instead of ISO strings (6f651d0)
  • task: correct task_search documented default limit to 50 (f53a1ac)
  • task: enforce expectedModifiedAt guard in task_defer_smart (3c90a60)
  • task: exclude dropped tasks from task_reclassify and task_find_similar (6186f82)
  • task: include limit in the task_list cache key (90ff6e1)
  • task: validate image path before any write in task_extract_from_image (2d59d2b)
  • transport: append jxa errorNumber to persistent error frames (2d445d6)
  • transport: decode fd3 and stderr with stateful utf-8 decoders (bda0c3e)
  • transport: execute expression-form scripts once in persistent dispatch (12f97a7)
  • transport: handle stdin errors on the persistent child via restart path (42acf53)
  • transport: surface typed OF_UNSUPPORTED when the jxa bridge rejects noteHtml (b821068)
  • transport: wire noteHtml through jxa update payloads and scripts (deb364a)
  • watcher: evict parent-task and containing-project payloads on targeted eviction (c4d02c2)
  • watcher: flush list-shaped cache scopes on targeted eviction (1b831e1)
  • webhooks: decompose url host into hostname and port for https delivery (86fd412)
  • webhooks: emit task-completed for tasks created and completed in one window (289d674)
  • webhooks: gate snapshot observation and delivery on the webhooks env flag (400e72b)
  • webhooks: serialize snapshot capture so stale fetches cannot regress the diff baseline (5052fcd)