Skip to main content
Glama

Write events

write_events

Create, update (edit, move, resize), shift, reflect, or manage a block's checklist — one or many in a single call. Pass ops, an array where each item has an op (create | update | shift | reflect | checklist) plus that op's fields; a single edit is a 1-item array. A span is start + end as local datetimes "YYYY-MM-DDTHH:MM" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event simply ends on a later day. A bare series id addresses the whole series; seriesId@YYYY-MM-DD addresses one occurrence; add scope:"future" to an occurrence id for that occurrence and every later one. update with start/end moves or resizes an event, also to another day; a lone start keeps the duration and a lone end keeps the start. shift nudges by byMinutes. reflect records how a PAST planned event actually went (kept | skipped | changed | added; actual times only for changed/added) — it never renames or re-times the plan. checklist manages a block's microtasks: items replaces the ordered list (bare id = the series template, occurrence id = that day), and check/uncheck take item ids and tick them off for one occurrence. Recurrence is an RRULE; null on update stops the repeat. Reference areas and activity types by areaId/activityTypeId (null on update clears the link; null on create is the same as omitted); create new ones first with manage_categories. calendarId is the home calendar (omit = the default calendar, null = dial only) and mirrorCalendarIds the one-way copies. If you know the duration but not a conflict-free time, use schedule instead of a create. By default the whole batch is atomic: if ANY op fails (e.g. a conflict), nothing is written and the failing ops are returned as errors — fix and resend. Pass partial: true for best-effort. Ops apply in order as one transaction and are checked against each other: two creates can't double-book a slot, and an earlier move frees a slot a later op can reuse. Target each event id at most once per batch. Changes to a calendar-linked event also reach that calendar; don't edit an event marked readOnly (the change would silently revert). To remove events or clear days use delete_events. The response has per-op results (each with its 0-based index), one undoToken + expiresAt, and timezone when a result carries a span.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
opsYes
renderNoWhen the user is looking at their reassign dial, set true to repaint it with the updated day in this same call. Otherwise the change reaches an open dial only if the host forwards this result.
partialNoBest-effort mode: apply the ops that succeed and report the rest as errors, instead of the default all-or-nothing.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "activityTypeId": {
      -        "description": "The activity type id (from the schedule read). null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "areaId": {
      -        "description": "The area id (from the schedule read). null or omitted leaves it unset.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "calendarId": {
      -        "description": "The home calendar: a calendar id (from the calendars list or the schedule's `integrations`). Omit it to use the account's default calendar if one is set, else the event stays on the dial only. null keeps the event on the dial only. A calendar id requires Reassign Pro; whole-series only.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "checklist": {
      -        "additionalProperties": false,
      -        "description": "Starter microtasks written to the new event's checklist.",
      -        "properties": {
      -          "items": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "done": {
      -                  "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      -                  "type": "boolean"
      -                },
      -                "id": {
      -                  "description": "Keep an existing item's id; omit for a new item.",
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "text": {
      -                  "maxLength": 200,
      -                  "minLength": 1,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "text"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 100,
      -            "type": "array"
      -          }
      -        },
      -        "required": [
      -          "items"
      -        ],
      -        "type": "object"
      -      },
      -      "end": {
      -        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "focusIntervals": {
      -        "additionalProperties": false,
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it.",
      -        "properties": {
      -          "breakMin": {
      -            "maximum": 60,
      -            "minimum": 1,
      -            "type": "integer"
      -          },
      -          "focusMin": {
      -            "maximum": 180,
      -            "minimum": 5,
      -            "type": "integer"
      -          }
      -        },
      -        "required": [
      -          "focusMin",
      -          "breakMin"
      -        ],
      -        "type": "object"
      -      },
      -      "id": {
      -        "description": "Optional client-minted event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non_blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorCalendarIds": {
      -        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats, as an RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "sourceUrl": {
      -        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      -        "maxLength": 2048,
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Its day is the event's day.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "activityTypeId": {
      -        "description": "The activity type id (from the schedule read). null clears the link; omit to keep it.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "areaId": {
      -        "description": "The area id (from the schedule read). null clears the link; omit to keep it.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "calendarId": {
      -        "description": "Re-home the event: a calendar id (from the calendars list or the schedule's `integrations`) moves it to that calendar; null unlinks it (keeps the dial block). Omit to keep the current home. Requires Reassign Pro; whole-series only.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "end": {
      -        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A lone end keeps the start.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "focusIntervals": {
      -        "anyOf": [
      -          {
      -            "additionalProperties": false,
      -            "properties": {
      -              "breakMin": {
      -                "maximum": 60,
      -                "minimum": 1,
      -                "type": "integer"
      -              },
      -              "focusMin": {
      -                "maximum": 180,
      -                "minimum": 5,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "focusMin",
      -              "breakMin"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it. Pass null to remove an existing rhythm."
      -      },
      -      "id": {
      -        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non_blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non_blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorCalendarIds": {
      -        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "A new RRULE for the series; null stops the repeat.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "const": "future",
      -        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      -        "type": "string"
      -      },
      -      "sourceUrl": {
      -        "anyOf": [
      -          {
      -            "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      -            "maxLength": 2048,
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Replace where this event was captured from (http(s)); null clears it. Whole-series only."
      -      },
      -      "start": {
      -        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A new start moves the event, also to another day (on an occurrence id, that occurrence only). A lone start keeps the duration.",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "const": "future",
      -        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualStart, only for \"changed\" or \"added\".",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualEnd, only for \"changed\" or \"added\".",
      -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a schedule or search read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart + actualEnd to record the real time); \"added\" = unplanned but happened (its actualStart + actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "check": {
      -        "description": "Item ids to mark DONE for the occurrence. On a recurring event this ticks off that occurrence only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a schedule or search read. A bare series id edits the template of the whole series; the `seriesId@YYYY-MM-DD` id edits or ticks off that one occurrence.",
      -        "type": "string"
      -      },
      -      "items": {
      -        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      -        "items": {
      -          "additionalProperties": false,
      -          "properties": {
      -            "done": {
      -              "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      -              "type": "boolean"
      -            },
      -            "id": {
      -              "description": "Keep an existing item's id; omit for a new item.",
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "text": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "text"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "op": {
      -        "const": "checklist",
      -        "type": "string"
      -      },
      -      "uncheck": {
      -        "description": "Item ids to mark NOT-done for the occurrence.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "The activity type id (from the schedule read). null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "The area id (from the schedule read). null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "calendarId": {
      +        "description": "The home calendar: a calendar id (from the calendars list or the schedule's `integrations`). Omit it to use the account's default calendar if one is set, else the event stays on the dial only. null keeps the event on the dial only. A calendar id requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "checklist": {
      +        "additionalProperties": false,
      +        "description": "Starter microtasks written to the new event's checklist.",
      +        "properties": {
      +          "items": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "done": {
      +                  "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      +                  "type": "boolean"
      +                },
      +                "id": {
      +                  "description": "Keep an existing item's id; omit for a new item.",
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "text": {
      +                  "maxLength": 200,
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "text"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 100,
      +            "type": "array"
      +          }
      +        },
      +        "required": [
      +          "items"
      +        ],
      +        "type": "object"
      +      },
      +      "end": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "focusIntervals": {
      +        "additionalProperties": false,
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "id": {
      +        "description": "Optional client-minted event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorCalendarIds": {
      +        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. An id already on the event may stay even if its calendar is read-only now; only an added id is checked. Adding an id requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats, as an RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Its day is the event's day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "The activity type id (from the schedule read). null clears the link; omit to keep it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "The area id (from the schedule read). null clears the link; omit to keep it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "calendarId": {
      +        "description": "Re-home the event: a calendar id (from the calendars list or the schedule's `integrations`) moves it to that calendar; null unlinks it and deletes its mirror copies (keeps the dial block). An unlink may carry start, end, name, notes, areaId, activityTypeId and kind, applied first in the same write. Omit to keep the current home. A calendar id requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "end": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A lone end keeps the start.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non_blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorCalendarIds": {
      +        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. An id already on the event may stay even if its calendar is read-only now; only an added id is checked. Adding an id requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "A new RRULE for the series; null stops the repeat.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "const": "future",
      +        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "anyOf": [
      +          {
      +            "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +            "maxLength": 2048,
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Replace where this event was captured from (http(s)); null clears it. Whole-series only."
      +      },
      +      "start": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A new start moves the event, also to another day (on an occurrence id, that occurrence only). A lone start keeps the duration.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "const": "future",
      +        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualStart, only for \"changed\" or \"added\".",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualEnd, only for \"changed\" or \"added\".",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a schedule or search read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart + actualEnd to record the real time); \"added\" = unplanned but happened (its actualStart + actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "check": {
      +        "description": "Item ids to mark DONE for the occurrence. On a recurring event this ticks off that occurrence only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a schedule or search read. A bare series id edits the template of the whole series; the `seriesId@YYYY-MM-DD` id edits or ticks off that one occurrence.",
      +        "type": "string"
      +      },
      +      "items": {
      +        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "done": {
      +              "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      +              "type": "boolean"
      +            },
      +            "id": {
      +              "description": "Keep an existing item's id; omit for a new item.",
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "op": {
      +        "const": "checklist",
      +        "type": "string"
      +      },
      +      "uncheck": {
      +        "description": "Item ids to mark NOT-done for the occurrence.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed4 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • removedInput schema / properties / concise
      Removed value: -{
      -  "description": "Drop the human-readable `suggestedFollowup` prose from the response (the structured `undoToken` is still returned). Saves tokens.",
      -  "type": "boolean"
      -}
    • removedInput schema / properties / ops / items / default
      Removed value: -{
      -  "op": "__invalid__"
      -}
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "checklist": {
      -        "description": "Starter microtasks written to the new event's checklist.",
      -        "items": {
      -          "properties": {
      -            "id": {
      -              "type": "string"
      -            },
      -            "text": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "text"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      -        "properties": {
      -          "breakMin": {
      -            "maximum": 60,
      -            "minimum": 1,
      -            "type": "integer"
      -          },
      -          "focusMin": {
      -            "maximum": 180,
      -            "minimum": 5,
      -            "type": "integer"
      -          }
      -        },
      -        "required": [
      -          "focusMin",
      -          "breakMin"
      -        ],
      -        "type": "object"
      -      },
      -      "id": {
      -        "description": "Optional client-minted section id. The onboarding funnel supplies it so the reveal step can read the new rows back; omit to let the server mint.",
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorTo": {
      -        "description": "Also fan this event out as one-way copies to these calendar ids (on top of the home from `syncTo`). The home id is dropped if listed. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Publish this event to one of the user's calendars: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`). Omit to follow the user's default calendar; pass null to force it dial-only. Requires Reassign Pro; whole-series only.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "anyOf": [
      -          {
      -            "properties": {
      -              "breakMin": {
      -                "maximum": 60,
      -                "minimum": 1,
      -                "type": "integer"
      -              },
      -              "focusMin": {
      -                "maximum": 180,
      -                "minimum": 5,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "focusMin",
      -              "breakMin"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorTo": {
      -        "description": "Replace the one-way copy set with these calendar ids; pass [] to clear all copies. The home calendar is dropped if listed. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Re-home this event: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`) moves it to that calendar; null unlinks it (removes it from the calendar, keeps the dial block). Omit to leave the current home. Requires Reassign Pro; whole-series only.",
      -        "type": [
      -          "string",
      -          "null"
      -        ]
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "actualEndNextDay": {
      -        "description": "Set true when the actual run crossed midnight.",
      -        "type": "boolean"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "check": {
      -        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      -        "type": "string"
      -      },
      -      "items": {
      -        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      -        "items": {
      -          "properties": {
      -            "id": {
      -              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      -              "type": "string"
      -            },
      -            "text": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "text"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "occurrenceDate": {
      -        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "checklist",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "uncheck": {
      -        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "The activity type id (from the schedule read). null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "The area id (from the schedule read). null or omitted leaves it unset.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "calendarId": {
      +        "description": "The home calendar: a calendar id (from the calendars list or the schedule's `integrations`). Omit it to use the account's default calendar if one is set, else the event stays on the dial only. null keeps the event on the dial only. A calendar id requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "checklist": {
      +        "additionalProperties": false,
      +        "description": "Starter microtasks written to the new event's checklist.",
      +        "properties": {
      +          "items": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "done": {
      +                  "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      +                  "type": "boolean"
      +                },
      +                "id": {
      +                  "description": "Keep an existing item's id; omit for a new item.",
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "text": {
      +                  "maxLength": 200,
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "text"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 100,
      +            "type": "array"
      +          }
      +        },
      +        "required": [
      +          "items"
      +        ],
      +        "type": "object"
      +      },
      +      "end": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "focusIntervals": {
      +        "additionalProperties": false,
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "id": {
      +        "description": "Optional client-minted event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non_blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorCalendarIds": {
      +        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats, as an RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Its day is the event's day.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "activityTypeId": {
      +        "description": "The activity type id (from the schedule read). null clears the link; omit to keep it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "areaId": {
      +        "description": "The area id (from the schedule read). null clears the link; omit to keep it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "calendarId": {
      +        "description": "Re-home the event: a calendar id (from the calendars list or the schedule's `integrations`) moves it to that calendar; null unlinks it (keeps the dial block). Omit to keep the current home. Requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "end": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A lone end keeps the start.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "additionalProperties": false,
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus. A non_blocking or reference event rejects it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non_blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non_blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorCalendarIds": {
      +        "description": "The one-way copy calendars, as calendar ids. It must not contain the home `calendarId`. On update it REPLACES the set; [] clears it. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "A new RRULE for the series; null stops the repeat.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive last day of the repeat, \"YYYY-MM-DD\". Needs `recurrence`.",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "const": "future",
      +        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "anyOf": [
      +          {
      +            "description": "Where this was captured from — the http(s) page address. Shown as a source chip; never parsed. Set it only for something grabbed off a real page, not for an intention the user typed.",
      +            "maxLength": 2048,
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Replace where this event was captured from (http(s)); null clears it. Whole-series only."
      +      },
      +      "start": {
      +        "description": "Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. A new start moves the event, also to another day (on an occurrence id, that occurrence only). A lone start keeps the duration.",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "description": "The event id from a read. A bare series id addresses the whole series; `seriesId@YYYY-MM-DD` addresses one occurrence.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "const": "future",
      +        "description": "Only with a `seriesId@YYYY-MM-DD` id: \"future\" edits that occurrence and every later one. Omit it to edit only that occurrence; a bare series id edits the whole series.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualStart, only for \"changed\" or \"added\".",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started. Local datetime \"YYYY-MM-DDTHH:MM\" (no seconds, offset or Z). The end must be after the start; an overnight or multi-day event just ends on a later day. Send it with actualEnd, only for \"changed\" or \"added\".",
      +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a schedule or search read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart + actualEnd to record the real time); \"added\" = unplanned but happened (its actualStart + actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "check": {
      +        "description": "Item ids to mark DONE for the occurrence. On a recurring event this ticks off that occurrence only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a schedule or search read. A bare series id edits the template of the whole series; the `seriesId@YYYY-MM-DD` id edits or ticks off that one occurrence.",
      +        "type": "string"
      +      },
      +      "items": {
      +        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "done": {
      +              "description": "true ticks the item off, false clears it; omit to keep the current state (a new item starts not done).",
      +              "type": "boolean"
      +            },
      +            "id": {
      +              "description": "Keep an existing item's id; omit for a new item.",
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "op": {
      +        "const": "checklist",
      +        "type": "string"
      +      },
      +      "uncheck": {
      +        "description": "Item ids to mark NOT-done for the occurrence.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  3. Changed2 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      -        "properties": {
      -          "breakMin": {
      -            "maximum": 60,
      -            "minimum": 1,
      -            "type": "integer"
      -          },
      -          "focusMin": {
      -            "maximum": 180,
      -            "minimum": 5,
      -            "type": "integer"
      -          }
      -        },
      -        "required": [
      -          "focusMin",
      -          "breakMin"
      -        ],
      -        "type": "object"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorTo": {
      -        "description": "Also fan this event out as one-way copies to these calendar ids (on top of the home from `syncTo`). The home id is dropped if listed. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Publish this event to one of the user's calendars: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`). Omit to follow the user's default calendar; pass null to force it dial-only. Requires Reassign Pro; whole-series only."
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "anyOf": [
      -          {
      -            "properties": {
      -              "breakMin": {
      -                "maximum": 60,
      -                "minimum": 1,
      -                "type": "integer"
      -              },
      -              "focusMin": {
      -                "maximum": 180,
      -                "minimum": 5,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "focusMin",
      -              "breakMin"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "mirrorTo": {
      -        "description": "Replace the one-way copy set with these calendar ids; pass [] to clear all copies. The home calendar is dropped if listed. Requires Reassign Pro; whole-series only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Re-home this event: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`) moves it to that calendar; null unlinks it (removes it from the calendar, keeps the dial block). Omit to leave the current home. Requires Reassign Pro; whole-series only."
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "actualEndNextDay": {
      -        "description": "Set true when the actual run crossed midnight.",
      -        "type": "boolean"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "check": {
      -        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      -        "type": "string"
      -      },
      -      "items": {
      -        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      -        "items": {
      -          "properties": {
      -            "id": {
      -              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      -              "type": "string"
      -            },
      -            "text": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "text"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "occurrenceDate": {
      -        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "checklist",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "uncheck": {
      -        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "checklist": {
      +        "description": "Starter microtasks written to the new event's checklist.",
      +        "items": {
      +          "properties": {
      +            "id": {
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "id": {
      +        "description": "Optional client-minted section id. The onboarding funnel supplies it so the reveal step can read the new rows back; omit to let the server mint.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorTo": {
      +        "description": "Also fan this event out as one-way copies to these calendar ids (on top of the home from `syncTo`). The home id is dropped if listed. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Publish this event to one of the user's calendars: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`). Omit to follow the user's default calendar; pass null to force it dial-only. Requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorTo": {
      +        "description": "Replace the one-way copy set with these calendar ids; pass [] to clear all copies. The home calendar is dropped if listed. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Re-home this event: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`) moves it to that calendar; null unlinks it (removes it from the calendar, keeps the dial block). Omit to leave the current home. Requires Reassign Pro; whole-series only.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "actualEndNextDay": {
      +        "description": "Set true when the actual run crossed midnight.",
      +        "type": "boolean"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "check": {
      +        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      +        "type": "string"
      +      },
      +      "items": {
      +        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      +        "items": {
      +          "properties": {
      +            "id": {
      +              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "occurrenceDate": {
      +        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "checklist",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "uncheck": {
      +        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  4. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      -        "properties": {
      -          "breakMin": {
      -            "maximum": 60,
      -            "minimum": 1,
      -            "type": "integer"
      -          },
      -          "focusMin": {
      -            "maximum": 180,
      -            "minimum": 5,
      -            "type": "integer"
      -          }
      -        },
      -        "required": [
      -          "focusMin",
      -          "breakMin"
      -        ],
      -        "type": "object"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "anyOf": [
      -          {
      -            "properties": {
      -              "breakMin": {
      -                "maximum": 60,
      -                "minimum": 1,
      -                "type": "integer"
      -              },
      -              "focusMin": {
      -                "maximum": 180,
      -                "minimum": 5,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "focusMin",
      -              "breakMin"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "actualEndNextDay": {
      -        "description": "Set true when the actual run crossed midnight.",
      -        "type": "boolean"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "check": {
      -        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      -        "type": "string"
      -      },
      -      "items": {
      -        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      -        "items": {
      -          "properties": {
      -            "id": {
      -              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      -              "type": "string"
      -            },
      -            "text": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "text"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      },
      -      "occurrenceDate": {
      -        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "checklist",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "uncheck": {
      -        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "maxItems": 100,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorTo": {
      +        "description": "Also fan this event out as one-way copies to these calendar ids (on top of the home from `syncTo`). The home id is dropped if listed. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Publish this event to one of the user's calendars: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`). Omit to follow the user's default calendar; pass null to force it dial-only. Requires Reassign Pro; whole-series only."
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "mirrorTo": {
      +        "description": "Replace the one-way copy set with these calendar ids; pass [] to clear all copies. The home calendar is dropped if listed. Requires Reassign Pro; whole-series only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Re-home this event: a calendar id from GET /api/v1/calendars (or get_schedule's `integrations`) moves it to that calendar; null unlinks it (removes it from the calendar, keeps the dial block). Omit to leave the current home. Requires Reassign Pro; whole-series only."
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "actualEndNextDay": {
      +        "description": "Set true when the actual run crossed midnight.",
      +        "type": "boolean"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "check": {
      +        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      +        "type": "string"
      +      },
      +      "items": {
      +        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      +        "items": {
      +          "properties": {
      +            "id": {
      +              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "occurrenceDate": {
      +        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "checklist",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "uncheck": {
      +        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  5. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      -        "properties": {
      -          "breakMin": {
      -            "maximum": 60,
      -            "minimum": 1,
      -            "type": "integer"
      -          },
      -          "focusMin": {
      -            "maximum": 180,
      -            "minimum": 5,
      -            "type": "integer"
      -          }
      -        },
      -        "required": [
      -          "focusMin",
      -          "breakMin"
      -        ],
      -        "type": "object"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "focusIntervals": {
      -        "anyOf": [
      -          {
      -            "properties": {
      -              "breakMin": {
      -                "maximum": 60,
      -                "minimum": 1,
      -                "type": "integer"
      -              },
      -              "focusMin": {
      -                "maximum": 180,
      -                "minimum": 5,
      -                "type": "integer"
      -              }
      -            },
      -            "required": [
      -              "focusMin",
      -              "breakMin"
      -            ],
      -            "type": "object"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "actualEndNextDay": {
      -        "description": "Set true when the actual run crossed midnight.",
      -        "type": "boolean"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "actualEndNextDay": {
      +        "description": "Set true when the actual run crossed midnight.",
      +        "type": "boolean"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "check": {
      +        "description": "Mark these items DONE for the occurrence, by item id or exact text. On a recurring event this ticks off THIS occurrence only.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To edit or tick off ONE occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day.",
      +        "type": "string"
      +      },
      +      "items": {
      +        "description": "REPLACE the whole checklist with these microtasks, in order — add, rename, remove, and reorder are all expressed as the resulting list. Read the current items first, then send the full desired list. Pass [] to clear the checklist. A checkoff on a removed item is dropped automatically.",
      +        "items": {
      +          "properties": {
      +            "id": {
      +              "description": "Keep an existing item's id (from a read) to preserve its checked state; omit to add a new microtask.",
      +              "type": "string"
      +            },
      +            "text": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "text"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      },
      +      "occurrenceDate": {
      +        "description": "The occurrence to edit, \"YYYY-MM-DD\", for a scope:\"this\" template edit on a recurring event (or supply the composite `seriesId@YYYY-MM-DD` id).",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "checklist",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "description": "For a recurring TEMPLATE edit (`items`): \"all\" (every occurrence, the default) or \"this\" (one occurrence — needs an occurrence id or `occurrenceDate`). Ticking items off is ALWAYS per-occurrence, so it ignores this.",
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "uncheck": {
      +        "description": "Mark these items NOT-done for the occurrence, by item id or exact text.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 100,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  6. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "actualEnd": {
      -        "description": "When it actually ended, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "actualEndNextDay": {
      -        "description": "Set true when the actual run crossed midnight.",
      -        "type": "boolean"
      -      },
      -      "actualStart": {
      -        "description": "When it actually started, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "reflect",
      -        "type": "string"
      -      },
      -      "status": {
      -        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      -        "enum": [
      -          "kept",
      -          "skipped",
      -          "changed",
      -          "added"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "status"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it.",
      +        "properties": {
      +          "breakMin": {
      +            "maximum": 60,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          "focusMin": {
      +            "maximum": 180,
      +            "minimum": 5,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "focusMin",
      +          "breakMin"
      +        ],
      +        "type": "object"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "focusIntervals": {
      +        "anyOf": [
      +          {
      +            "properties": {
      +              "breakMin": {
      +                "maximum": 60,
      +                "minimum": 1,
      +                "type": "integer"
      +              },
      +              "focusMin": {
      +                "maximum": 180,
      +                "minimum": 5,
      +                "type": "integer"
      +              }
      +            },
      +            "required": [
      +              "focusMin",
      +              "breakMin"
      +            ],
      +            "type": "object"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Split a BLOCKING block into a repeating focus/break rhythm (pomodoro), e.g. {focusMin:25,breakMin:5}. The breaks fall BETWEEN the focus intervals and the block always ends on a focus — both derived from the block's length, so you never list individual intervals. Only valid on a blocking event; a non-blocking/reference block ignores it. Pass null to remove an existing rhythm."
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "actualEndNextDay": {
      +        "description": "Set true when the actual run crossed midnight.",
      +        "type": "boolean"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  }
      +]
  7. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "actualEnd": {
      +        "description": "When it actually ended, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "actualEndNextDay": {
      +        "description": "Set true when the actual run crossed midnight.",
      +        "type": "boolean"
      +      },
      +      "actualStart": {
      +        "description": "When it actually started, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "description": "The event id, echoed verbatim from a get_schedule/find_event read. To mark one occurrence of a recurring event, pass the `seriesId@YYYY-MM-DD` id the read returned for that day — don't fabricate the @date yourself.",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "reflect",
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "How a past planned event actually went. \"kept\" = happened as planned; \"skipped\" = didn't happen; \"changed\" = happened but differently (pass actualStart/actualEnd to record the real time, otherwise it's logged as changed with no exact time); \"added\" = unplanned but happened (its actualStart/actualEnd become the event's time). Marking only records the reflection — it never renames or re-times the plan.",
      +        "enum": [
      +          "kept",
      +          "skipped",
      +          "changed",
      +          "added"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "status"
      +    ],
      +    "type": "object"
      +  }
      +]
  8. Changed1 schema field changed
    • changedInput schema / properties / ops / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "kind": {
      -        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting or sleep band) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "date",
      -      "start",
      -      "end",
      -      "name"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "activityTypeId": {
      -        "type": "string"
      -      },
      -      "activityTypeName": {
      -        "description": "Activity type by name instead of id.",
      -        "type": "string"
      -      },
      -      "areaId": {
      -        "type": "string"
      -      },
      -      "areaName": {
      -        "description": "Area by name instead of id (case/accent-insensitive).",
      -        "type": "string"
      -      },
      -      "date": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "end": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "endNextDay": {
      -        "type": "boolean"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "kind": {
      -        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      -        "enum": [
      -          "blocking",
      -          "non-blocking",
      -          "reference"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "maxLength": 200,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "notes": {
      -        "maxLength": 2000,
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "recurrence": {
      -        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      -        "type": "string"
      -      },
      -      "recurrenceEnd": {
      -        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      },
      -      "syncTo": {
      -        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "date": {
      -        "description": "New date, ISO \"YYYY-MM-DD\".",
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      },
      -      "start": {
      -        "description": "New start time, 24-hour \"HH:MM\".",
      -        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "byMinutes": {
      -        "description": "Minutes to shift by; negative is earlier.",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "id": {
      -        "type": "string"
      -      },
      -      "occurrenceDate": {
      -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "shift",
      -        "type": "string"
      -      },
      -      "scope": {
      -        "enum": [
      -          "all",
      -          "future",
      -          "this"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id",
      -      "byMinutes"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "kind": {
      +        "description": "\"blocking\" (default) cannot overlap others; \"non-blocking\" is an overlay (e.g. a fasting band or an away/OOO marker) that may overlap and never conflicts; \"reference\" is something the user wants to SEE but isn't doing (e.g. a kid's training they drop off at) — non-blocking, and don't move, delete, or schedule work into it unless asked.",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "How the event repeats: a preset (daily, weekdays, weekly, biweekly, monthly, yearly) or a raw RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Inclusive end date for the repeat, \"YYYY-MM-DD\" (that day is the last occurrence). Only meaningful with `recurrence`; ignored for a one-off.",
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "date",
      +      "start",
      +      "end",
      +      "name"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "activityTypeId": {
      +        "type": "string"
      +      },
      +      "activityTypeName": {
      +        "description": "Activity type by name instead of id.",
      +        "type": "string"
      +      },
      +      "areaId": {
      +        "type": "string"
      +      },
      +      "areaName": {
      +        "description": "Area by name instead of id (case/accent-insensitive).",
      +        "type": "string"
      +      },
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "end": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "endNextDay": {
      +        "type": "boolean"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Change the event kind: \"blocking\", \"non-blocking\", or \"reference\" (see-only — non-blocking, don't schedule work into it).",
      +        "enum": [
      +          "blocking",
      +          "non-blocking",
      +          "reference"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "maxLength": 200,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "notes": {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "recurrence": {
      +        "description": "New recurrence (preset or RRULE); set to \"none\" to stop repeating.",
      +        "type": "string"
      +      },
      +      "recurrenceEnd": {
      +        "description": "Set or replace the repeat end date, \"YYYY-MM-DD\" (inclusive), or \"none\" to make it open-ended. Carried across a frequency change. One-off: ignored.",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      },
      +      "syncTo": {
      +        "description": "Set by the dial widget's “Sync to” picker — the calendar id to publish this (dial-only) event to. The user picks it in the editor; leave it unset, a created/edited event already follows the user's default calendar.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "date": {
      +        "description": "New date, ISO \"YYYY-MM-DD\".",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      },
      +      "start": {
      +        "description": "New start time, 24-hour \"HH:MM\".",
      +        "pattern": "^([01]?\\d|2[0-3]):[0-5]\\d$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "byMinutes": {
      +        "description": "Minutes to shift by; negative is earlier.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "occurrenceDate": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "shift",
      +        "type": "string"
      +      },
      +      "scope": {
      +        "enum": [
      +          "all",
      +          "future",
      +          "this"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id",
      +      "byMinutes"
      +    ],
      +    "type": "object"
      +  }
      +]
  9. Changed1 schema field changed
    • addedInput schema / properties / ops / items / default
      Added value: +{
      +  "op": "__invalid__"
      +}
  10. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are minimal (three hints), so the description carries the behavioral burden and does so thoroughly: it discloses default atomicity with all-or-nothing semantics on any failure, transactional ordering with cross-op conflict checking, the one-id-per-batch constraint, the readOnly silent-revert pitfall, calendar-link propagation to mirrors, and the response shape (per-op results, undoToken, expiresAt, timezone). No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the purpose and op list, and every sentence earns its place given the tool's complexity — five op types plus cross-cutting semantics, atomicity, and routing. However, it is a single dense paragraph; breaking it into op-type or concern-based sections would improve scannability for agents.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with five op variants, no output schema, and minimal annotations, the description is remarkably complete: it covers edge cases (duration-preserving moves, overnight events), failure/retry behavior with partial mode, intra-batch conflict checking, series occurrence addressing, and the readOnly warning. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 67% schema coverage, the description adds substantial meaning: the time format constraint is repeated, and it explains op-specific semantics the schema cannot — lone start keeps duration, lone end keeps start, series addressing forms (bare id vs seriesId@YYYY-MM-DD vs scope:"future"), reflect's non-mutating behavior, and null-clears versus omit-keeps distinctions across fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states specific verbs and a resource: create, update, shift, reflect, and checklist operations on blocks/events, in one batch call. It differentiates from siblings explicitly — 'use `schedule` instead of a create' when duration is known but a conflict-free time isn't, and 'use delete_events' for removal — so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: create new categories first with manage_categories, prefer schedule when a conflict-free slot isn't known, and route removal to delete_events. It also explains when partial:true is appropriate (best-effort) versus the default atomic batch, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.