Skip to main content
Glama

Server Details

Reassign: a circular 24-hour calendar and time-tracking copilot with ADHD-friendly scheduling.

Ownership verified
Status
Healthy
Uptime
99.6% over 59 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
reassignai/plugins
GitHub Stars
1

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation4/5

Most tools have clearly distinct resource/action targets such as reading the schedule, writing/deleting events, managing the Inbox, and managing categories. Minor overlap remains around moving items between Inbox and dial (manage_inbox schedule/park) versus write_events/delete_events, and find_event/get_schedule both read events and Inbox items, but the descriptions explicitly disambiguate these boundaries.

Naming Consistency5/5

All 11 tools use snake_case verb_noun naming (delete_events, find_event, get_schedule, manage_inbox, write_events, undo_changes), with a predictable verb-first convention. Minor variations like get_more_tools still follow the pattern and remain readable.

Tool Count5/5

11 tools are well-scoped for a calendar and Inbox assistant: read, search, write, delete, inbox management, categories, review, undo, visualization, and meta feedback. Each tool maps to a distinct capability, with no obvious bloat or essential missing operation by count.

Completeness4/5

Core lifecycle coverage is strong: events via get_schedule/write_events/delete_events, Inbox CRUD and scheduling via manage_inbox, categories CRUD, undo, and day review. Minor gaps include no direct get_event-by-id operation and no dedicated calendar/integration management tool, though get_schedule’s integrations and search/read tools cover most workflows.

Available Tools

11 tools
delete_eventsDelete eventsA
Destructive
Inspect

Delete events or clear whole days — one or many in a single call. Pass ops, an array where each item has an op (delete | clear): delete removes one event by id. A bare series id addresses the whole series; seriesId@YYYY-MM-DD addresses one occurrence by its ORIGINAL date, also after a move (the read's id and originalDate give it); add scope:"future" to an occurrence id for that occurrence and every later one. clear removes everything from from to to (inclusive, equal for one day). By default the whole batch is atomic: if ANY op fails, nothing is removed; pass partial: true for best-effort. A recorded undo receipt includes undoToken (call undo_changes before expiresAt, a UTC instant). Deleting a calendar-linked event also removes it from that calendar; an event marked readOnly can't be deleted this way. A delete result lists deletedIds; a scope:"future" delete also returns the truncated series as updated. Results read stored state after the whole batch commits. To create or edit events use write_events.

ParametersJSON 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.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only declare destructiveHint=true; the description goes far beyond by disclosing the default all-or-nothing atomicity, the opt-in best-effort mode, an undo receipt with undoToken/expiresAt, the readOnly guard, that calendar-linked events are also removed from that calendar, and what the result object contains. This is rich behavioral context an agent needs before calling a destructive tool.

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?

Front-loaded with purpose and the ops contract, and every sentence carries information that is not in the schema. It is a dense block of text with many parentheticals, so readability suffers slightly, but there is almost no filler.

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 destructive, no-output-schema tool, the description covers invocation (ops shape), failure semantics (atomic vs partial), recovery (undoToken/expiresAt), edge cases (readOnly, series truncation returning updated), and return fields (deletedIds). Nothing material to correct invocation is missing.

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?

With 67% schema coverage, the description adds real meaning: the id format semantics (bare series id vs seriesId@YYYY-MM-DD by ORIGINAL date, surviving moves), the inclusive from/to range, and the batch semantics of ops. It explains parameter behavior beyond the schema's field-level text.

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?

Opens with a specific verb-and-resource ('Delete events or clear whole days'), and the closing sentence explicitly routes creation/editing to write_events, distinguishing this from the primary sibling. An agent can tell this apart from write_events and undo_changes without opening a schema.

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?

States exactly when to use each op path (delete vs clear), when to add scope:"future", when to choose partial:true over the atomic default, and names undo_changes as the recovery path before expiresAt. It also names write_events as the tool for the opposite operation. Exclusions and alternatives are explicit.

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

find_eventFind eventA
Read-only
Inspect

Search for, look up, or locate events and Inbox items by name when you do not have an id: case- and accent-insensitive. Events match fuzzily; Inbox items (un-timed blocks, not events) match when the name holds the query, and come back as inbox (top of tray first, the same shape as the get_schedule backlog items; write them with manage_inbox). Each page has up to 50 Inbox matches; inboxMatchedCount is the total. When nextInboxOffset is not null, pass it as inboxOffset with the same query and filters to read the next page. The offset only pages Inbox items. The date and timeOfDay filters apply to events only. Date ranges include events overlapping any requested day, including events that start earlier; ending exactly at the first midnight does not overlap. timeOfDay filters the event's start time. Events are searched from the past week through the next 30 days by default; pass from/to (ISO "YYYY-MM-DD", e.g. "2026-06-01") to widen or shift the window, and optionally filter by areaId, activityTypeId, or timeOfDay. Returns events (best match first, one per event, each with its name match score from 0 to 1, 1 = exact; a recurring event gives one occurrence with its seriesId: the best match, and on a tie the one nearest to today) in the same event shape as get_schedule, and the timezone of their times. An event with readOnly: true lives on a calendar the user does not own: do not edit or delete it. When two different events tie, ambiguous is true: ask the user which one they meant. Two days of the same recurring event are not ambiguous.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoRange end, ISO date, e.g. "2026-07-01". Defaults to +30 days.
fromNoRange start, ISO date, e.g. "2026-06-01". Defaults to 7 days ago.
queryYesText to match against event names, e.g. "standup", "gym".
areaIdNoOnly match events linked to this area id.
timeOfDayNoOnly match events that start in this part of the day.
inboxOffsetNoInbox page offset from nextInboxOffset; keep the same query and filters. Defaults to 0. Does not page the events.
activityTypeIdNoOnly match events linked to this activity-type id.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnlyHint and openWorldHint. The description adds substantial behavioral context beyond them: fuzzy event matching, case/accent-insensitivity, Inbox result shape, pagination rules, event-only filter behavior, date-overlap semantics, default time window, scoring, seriesId tie-breaking, and readOnly calendar handling.

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 long but front-loads the core purpose and is mostly dense with necessary edge cases for a 7-parameter search tool. It could be tightened slightly, such as the 'Search for, look up, or locate' synonym stack, but the length is largely justified.

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?

With no output schema, the description fully explains the return shape: events, timezone, score, seriesId, inbox results, inboxMatchedCount, nextInboxOffset, and ambiguity handling. It covers the tool's complexity and edge cases thoroughly enough for an agent to invoke and interpret it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema, including that from/to widen or shift the event search window, timeOfDay filters event start time, and inboxOffset pages only Inbox items. It is less detailed for areaId and activityTypeId, which the schema already explains adequately.

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?

States specific verbs and resources: search for, look up, or locate events and Inbox items by name when no id is available. It clearly distinguishes Inbox items from events and ties the event shape to get_schedule, letting an agent separate it from siblings 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?

Explicitly says to use this tool when you do not have an id, describes pagination behavior for Inbox matches, and routes writing to manage_inbox. It also explains default search window, how to widen it, and when to ask the user due to ambiguity.

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

get_more_toolsA
Read-onlyIdempotent
Inspect

Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.

ParametersJSON Schema
NameRequiredDescriptionDefault
contextYesA description of your goal and what kind of tool would help accomplish it.

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds no additional behavioral context such as what 'check' entails, whether it makes a network call, or what side effects (if any) occur beyond 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 a single, front-loaded sentence with no wasted words. It quickly communicates the action and the conditions for use, making it efficient and easy to parse, though it could be slightly more structured with a separate usage note.

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

Completeness3/5

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

The description gives clear usage guidance but does not explain what the tool returns or what happens after 'checking' for tools. With no output schema present, the description carries the burden of explaining the result, which it fails to do. For a simple one-parameter tool, this is a notable gap, though not severe.

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

Parameters3/5

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

Schema coverage is 100%, and the single parameter 'context' is already documented with a clear description in the schema. The tool description adds no additional semantic meaning beyond what the schema provides, which aligns with the baseline of 3.

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

Purpose4/5

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

The description clearly states the tool's function: checking for additional tools when a task could benefit from specialized capabilities. It distinguishes itself from the sibling clipform_* tools by being a meta-tool for tool discovery rather than a domain-specific operation, though it does not explicitly name this distinction.

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

Usage Guidelines4/5

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

The description provides explicit usage guidance: use this tool whenever specialized capabilities might help, even if existing tools could work as a fallback. This gives the agent a clear decision rule, though it does not mention when not to use it or list alternative tools.

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

get_scheduleGet schedule
Read-only
Inspect

Read the calendar: the agenda, what is on, how busy the user is, free time, or where the time goes. One call returns the current local time (now, "YYYY-MM-DDTHH:MM"), the user's timezone, the user's areas, activityTypes and projects (the lookup lists for areaId / activityTypeId / projectId; a project has an areaId; an archived project has archived: true, refuses new links, and comes back with a manage_categories update archived: false), userPreferences, and a days array. Each day has its events, its freeSlots, and its blocking load per area, activity type and project (projectId null is no project; non-blocking overlay load comes separately). A read of more than one day also has a top-level loadByProject, the sum of its days (for example, a week). Call it before you schedule, to anchor relative times ('this afternoon'). Pass from and to (ISO YYYY-MM-DD, inclusive; equal for one day). Pass includeSeries: true to also get the recurring series as series (the live ones and the ones in the range, with no notes). Pass includeLookups: false on a later call to leave out areas, activityTypes, projects and integrations.

Time spans: every event and free slot is start + end, two local datetimes "YYYY-MM-DDTHH:MM" in the top-level timezone (e.g. start "2026-09-23T22:00", end "2026-09-24T01:00"). The end is always after the start; a slot to midnight ends at the next day's T00:00. An event from an earlier day that runs into this day is listed first, with its real start, on every day that it touches; only its time inside the day counts for load and free slots. A warning marks a start time that a DST change skips.

Each event carries its source ("reassign", else a provider like "google"), its home calendarId (absent = the default calendar, null = dial only) and any mirrorCalendarIds (with mirrorStyles when a copy is private or busy). An event with readOnly: true is on a calendar the user does not own: do not edit or delete it (tell them to change it there). kind "non_blocking" is an overlay that may overlap others (fasting, an away marker); "reference" is see-only: its hours stay free, so do not move, delete, or schedule work into it unless asked. A confirmed past day carries a review adherence rollup and per-event reflect actuals; use them for how a day or week actually went. When a calendar is connected, integrations describes it (a calendar's timezone is information only; every span uses the top-level timezone; a calendar's copyStyle applies to copies when mirrorStyles omits that calendar). For a single day, a one-line weather headline is included when the user has a city. For one day, pass includeWeather: true for the full forecast (an outdoor plan only) and includeEnergy: true for the energy curve (energy: peak and dip windows from logged sleep), to put focus work in a peak.

Inbox: backlogCount is the number of Inbox blocks (un-timed intentions). Pass includeBacklog: true for the items (top of tray first, up to 50); backlogPlannedOn, backlogProjectId (an id or "none"), backlogMinPriority (0 to 4) and backlogOffset filter or page them and need includeBacklog: true; with a filter, backlogMatchedCount is the number of matches. Each item has a projectId and a priority (0 none, 1 low, 2 medium, 3 high, 4 urgent). To find an item by name, use find_event. When nextBacklogOffset is not null, pass it as backlogOffset with the same filters for the next page. Place or manage items with manage_inbox.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesLast day of the range, inclusive.
fromYesFirst day of the range, inclusive.
minDurationNoReturn only the `freeSlots` of at least this many minutes.
backlogOffsetNoInbox page offset from nextBacklogOffset; keep the same filters. Needs includeBacklog: true.
includeEnergyNoAdd `energy`: the user's forecast energy curve for the day (peak and dip windows, the current level today, calibration state), built from logged sleep. Use it to put focus work in a peak and admin in a dip. With no logged sleep it is a short nudge to log sleep. Needs one day (`from` equal to `to`).
includeSeriesNoAlso return the recurring masters as `series`.
includeBacklogNoInclude the Inbox items (the `backlog` array), not just `backlogCount`. Pass true when the user wants to see, schedule, or manage their Inbox.
includeLookupsNoDefault true. Pass false to leave out `areas`, `activityTypes`, `projects` and `integrations` when you already have them from an earlier read.
includeWeatherNoReplace the one-line `weather` headline with the full forecast for the day (condition, temperature range, rain window, daylight, and a part-of-day breakdown). Use it only for an outdoor or weather-sensitive plan, or when the user asks about the weather. Needs one day (`from` equal to `to`).
weatherLocationNoA city or place name to forecast instead of the user's own city, e.g. "London". The forecast date and times are local to that place; the report names its timezone. Needs includeWeather: true.
backlogPlannedOnNoFilter the Inbox blocks to those planned for this day (a planned day, or a planned window that covers it). Needs includeBacklog: true.
backlogProjectIdNoFilter the Inbox blocks to one project id, or "none" for the blocks with no project. Needs includeBacklog: true; composes with the other filters.
backlogMinPriorityNoFilter the Inbox blocks to a priority of at least this value (0 none, 1 low, 2 medium, 3 high, 4 urgent). Needs includeBacklog: true; composes with the other filters.
manage_categoriesManage categories
Destructive
Inspect

Create, update, or delete areas (categories / groups / colour-coded labels), activity types (tags / fill patterns) and projects (named goals under an area) — one or many in a single call. Pass areas, activityTypes and/or projects, each an array of ops: {op:"create", name, color?} / {op:"update", id, name?, color?} / {op:"delete", id, reassignTo?} for areas; pattern instead of color for activity types (valid patterns: solid, hatch_r, hatch_l, cross, horizontal, vertical, grid, dots, waves, chevron). Projects: {op:"create", name, areaId?} / {op:"update", id, name?, areaId?, order?, archived?} / {op:"delete", id} / {op:"split", id, linkId}. A split moves one task list or Linear project (linkId) that feeds the project to a new project of its own, "{name} ({Provider})" in the same area (" 2" on a taken name), with its Inbox items; later syncs keep it there. {op:"relink", id, linkId} points one Linear project (linkId) at the live project id, with its Inbox items. A project is your own (no shared defaults, no fork). areaId links it to an area; when a write moves an Inbox item to the project and sets no area, the item takes that area, also over an area set by hand. archived: true marks it archived in the lookups and refuses new links; its links stay; archived: false restores it. A delete clears the project link on its items and events (one undo restores them). A delete of a project that a synced task list or Linear project feeds fails with conflict: link it to another project first, or archive it. A project name is unique among the live projects of the user, in any area: a duplicate fails with conflict ("A project named Launch exists in Work."). Results come back in a projects array. Colours are lowercase "#rrggbb"; omit color or pattern to auto-pick. Editing a shared global default forks it into your own copy, so the returned id may differ — each result reports the effective id (and forkedFrom). A delete removes your own entry, or hides a shared default (and your copy of it) for you only. When events, Inbox items, trackers or calendar defaults use it, a delete without reassignTo is refused with validation; the error details give usage (the counts) and reassignTargets (the categories that can take them). Ask the user, then send the delete again with reassignTo (another id, to move them) or reassignTo: null (to clear their link). A project name is unique among all live projects of the user, so a moved project keeps its name. Names are deduplicated case-, accent- and whitespace-insensitively: a create or a rename into the name of an existing area/type fails with conflict (reuse the existing id instead). A create or update result is the created/updated row; a delete result lists deletedIds (plus movedEvents after a reassign). Every call that writes returns one undoToken + expiresAt (a UTC instant); pass it to undo_changes to reverse the whole call. Atomic by default: if any op is invalid nothing is written; pass partial: true for best-effort. Create areas/types here first, then reference the returned ids in write_events (and a project id in manage_inbox projectId).

ParametersJSON Schema
NameRequiredDescriptionDefault
areasNo
partialNoBest-effort mode instead of the default all-or-nothing.
projectsNo
activityTypesNo
manage_inboxManage Inbox
Destructive
Inspect

Write to the Inbox — the tray of time-blocks captured without a time yet: intentions like "wash the car" or "call the dentist". To READ Inbox blocks, use get_schedule (backlogCount, then includeBacklog: true for the items), or find_event to find one by name; THIS tool is the write surface. Pass ops, an array where each item has an op plus its fields — one or many in a single call, atomic by default (if any op fails nothing is written; pass partial: true for best-effort). Ops: capture creates an Inbox block (name, optional notes, durationMinutes, kind, checklist, areaId/activityTypeId, projectId, priority, and an optional plannedDate or plannedDate+plannedUntil window — the still-untimed days it is meant for; pass enrich: true for RAW captured text, e.g. a web-page selection, to have AI propose a readable name and a duration first — never for a name the user chose); capture_text takes what the user typed, dictated or selected, as text, and AI splits it into 1 to 10 Inbox blocks with a name, notes, a length and a day — prefer it over capture for raw user input, and send only the fields the user chose; update edits one by id (plannedDate: null moves it back to Someday; areaId/activityTypeId: null clears the link; projectId: null clears the project and keeps the area; a task-app-linked block's date is provider-owned and refused); remove deletes one by id; schedule PLACES an Inbox block on the dial at start (local "YYYY-MM-DDTHH:MM"; its duration sizes it; pass an RRULE recurrence to make it repeat) and removes it from the Inbox; park MOVES a dial event (by id) back into the Inbox. park only works on a native or owned-calendar one-off that hasn't been reviewed — a recurring, sleep, reviewed, or not-owned event is refused with a reason. Moving a calendar-linked event to the Inbox removes its calendar copy but remembers the calendar, so re-scheduling it republishes there. Results are created / updated objects and deletedIds. Every call that writes returns one undoToken + expiresAt; pass it to undo_changes to reverse the whole call. The Inbox needs Reassign Pro; the 7-day free trial includes it. schedule and park are inverses, and both keep the block's kind.

ParametersJSON Schema
NameRequiredDescriptionDefault
opsYes
partialNoBest-effort mode instead of the default all-or-nothing.
review_dayReview a dayA
Destructive
Inspect

Confirm or discard a whole day's reflection (by date, ISO YYYY-MM-DD), once you've marked its events with write_events' reflect op. action:"confirm" marks the day reviewed — "this is how it went" — freezing a per-day adherence snapshot (how closely actuals matched the plan, with per-area/per-type breakdowns), which get_schedule then returns as that day's review block and which the stats use; re-confirming refreshes it. action:"discard" fully resets the day: it removes the review, clears the kept/skipped/changed marks + actual times off the day's planned events (returned as updated), and deletes events ADDED only as part of the reflection (deletedIds) — use it to start a day's reflection over or drop one confirmed by mistake. Only a past day can be confirmed; discard works on any day, also on today's check-offs. A recorded undo receipt includes undoToken + expiresAt (UTC); call undo_changes before it expires. An empty discard returns noop:true, empty result arrays, and no undo receipt.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
actionYes"confirm" freezes the day's adherence snapshot; "discard" fully resets the day's reflection (removes the review, clears every mark).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only give destructiveHint=true; the description goes far beyond by enumerating exactly what is destroyed (review, kept/skipped/changed marks, actual times, and reflection-added events returned in `deletedIds`), what is created (adherence snapshot with per-area/per-type breakdowns), and the undo lifecycle (`undoToken` + `expiresAt` UTC). It also discloses the no-op edge case (empty discard returns `noop:true`, empty arrays, no receipt).

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?

Front-loaded with purpose, then actions, then side effects and undo — a sensible information hierarchy in a single dense paragraph. It is long for a two-parameter tool, and the action descriptions echo the schema's enum text nearly verbatim, which is minor redundancy, but almost every clause carries operational information.

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?

There is no output schema, and the description fills that gap by naming the returned fields (`updated`, `deletedIds`, `noop`, `undoToken`, `expiresAt`) and where the snapshot surfaces (`get_schedule`'s `review` block). For a destructive two-param mutation, everything an agent needs to call it safely and interpret the result is present.

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

Parameters4/5

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

Schema coverage is only 50% — `action` has an enum description but `date` has just a regex pattern with no prose. The description compensates by spelling out the ISO date format and, more importantly, elaborating the downstream consequences of each action value rather than restating the enum. It adds real meaning, though the date semantics are only lightly extended beyond the pattern.

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 names a specific verb pair and resource ('Confirm or discard a whole day's reflection') and immediately scopes it with the required `date` param. It distinguishes itself from siblings by naming write_events' `reflect` op as the precondition and undo_changes as the follow-up, so an agent can separate this from get_schedule or delete_events without opening a schema.

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?

Explicit preconditions ('once you've marked its events with write_events' `reflect` op'), explicit selection rules between the two actions, and explicit constraints ('Only a past day can be confirmed; discard works on any day'). It even names intended use cases — 'start a day's reflection over or drop one confirmed by mistake'.

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

send_feedbackSend feedbackAInspect

Report a bug, limitation, friction, or idea about reassign itself — its tools, their results, or this MCP integration — to the product team, who read every message. Covers errors, confusing or wrong results, retries or workarounds, loops, and rough edges that could be smoother, plus feedback the user asks to send. This is meta-feedback ABOUT the product, not a way to change the schedule (use write_events for events). Each report has a kind ("bug" | "idea" | "other") and a message. In message, describe what you tried, what happened, what you expected, and any event ids or steps to reproduce. Collect every report of the session into ONE call, with one item in reports for each issue. Do not call this tool once for each issue. Describe the problem in your own words — don't paste the user's personal details or private schedule contents; their account is attached automatically for follow-up. Returns {} once the report is accepted.

ParametersJSON Schema
NameRequiredDescriptionDefault
reportsYesAll reports of this session. Add one item for each issue.
submissionIdNoA UUID for this submission. Reuse it with identical content on retries within 24 hours; use a new UUID for a new report.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare the generic write/open-world profile; the description adds non-obvious behavior: the return value is `{}` on acceptance, the user's account is attached automatically for follow-up, and personal details or private schedule contents must not be pasted into the message. The batching rule (one call per session) is a behavioral constraint found nowhere in the structured fields.

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?

Purpose and scope lead the paragraph, followed by triggering conditions, then the exclusion, then per-field guidance and constraints. Dense and well ordered, though the long enumeration of triggering cases and the restated 'each report has a kind and message' sentence add some redundancy.

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 two-parameter write tool with no output schema, the description covers purpose, when to use, batching, privacy constraints, message content expectations, and the return value. An agent has everything needed to call it correctly and safely.

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

Parameters4/5

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

Schema description coverage is 100%, so the baseline is 3, but the description goes further: it defines the `kind` values semantically and specifies what a good `message` contains (what was tried, what happened, what was expected, event ids or reproduction steps), plus the one-item-per-issue structure of `reports`. It does not cover the `submissionId` retry semantics, which remain schema-only.

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 a precise verb and resource — report a bug, limitation, friction, or idea about the product itself — and explicitly scopes it to meta-feedback about the MCP integration and its results. It also names the sibling it is not (write_events for changing the schedule), so an agent can distinguish it without opening a schema.

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?

It enumerates the triggering conditions (errors, confusing or wrong results, retries, workarounds, loops, rough edges, user-requested feedback) and an explicit exclusion with the correct alternative (use write_events to change the schedule). It further prescribes when to batch versus split (one call per session, not one per issue).

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

show_dayShow day on the dialA
Read-only
Inspect

Render the user's day as the interactive 24-hour reassign dial, right in the conversation — use it whenever they want to SEE their day, their schedule laid out, how full it looks, or to visually move things around. Defaults to today; pass date (ISO YYYY-MM-DD) for another day. For reading or reasoning about the plan in text, prefer get_schedule.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNo

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds real behavioral context beyond that: the output is an interactive dial embedded in the conversation, the date defaults to today, and read-only textual reasoning belongs in get_schedule. It does not clarify whether the 'move things around' affordance mutates state (which would be worth stating against readOnlyHint), leaving a small gap.

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

Conciseness5/5

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

One tightly packed paragraph with zero filler: purpose front-loaded, then usage triggers, then default/format for the single parameter, then the routing alternative. Every clause earns its place and the ordering matches how an agent scans for a decision.

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

Completeness4/5

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

With no output schema, the description does describe what the agent gets back (an interactive dial rendered in the conversation) and covers the only parameter's default and format. What remains thin is the interactive surface itself — what the user can do inside the rendered dial and whether those actions change data — which matters given readOnlyHint=true.

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

Parameters4/5

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

There is only one parameter and schema description coverage is 0%, so the description must carry the meaning — and it does, stating the default ('Defaults to today') and the accepted format ('ISO YYYY-MM-DD'), which the schema only encodes as a regex pattern. It does not describe behavior for invalid or out-of-range dates, so it is not exhaustive.

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?

States a specific verb and resource ('Render the user's day as the interactive 24-hour reassign dial') and immediately scopes it as an in-conversation visual. It distinguishes itself from the closest sibling by explicitly naming get_schedule as the text alternative, so an agent can route without opening either schema.

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?

Gives an explicit trigger set ('whenever they want to SEE their day, their schedule laid out, how full it looks, or to visually move things around') and an explicit counter-condition ('For reading or reasoning about the plan in text, prefer get_schedule'). Both the when and the when-not are present with a named alternative.

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

undo_changesUndo recent changesA
Destructive
Inspect

Undo — revert, roll back, take back, or cancel the last — a recent write_events / delete_events batch, a review_day action, a manage_inbox call (capture, update, remove, schedule, park), or a manage_categories call (create, update, delete). Pass tokens: the undoToken those calls returned. Each works only while still active and before its expiresAt (a UTC instant, 30 minutes). A token reverses the whole change (delete what it created, restore what it changed or removed). If a row that the write touched changed again after the write (for example the event was moved, parked or deleted later), that token fails with stale and nothing changes. Stamp mismatches include conflictingRows with row ids and reasons (changed, deleted, newly_present), up to 50; conflictingRowsTruncated:true means more were omitted. Several tokens undo newest write first, so their order does not matter. Each result counts reverted, restored, removed and voided. To discard a whole day's reflection by date instead, use review_day with action 'discard'. Returns per-token results.

ParametersJSON Schema
NameRequiredDescriptionDefault
tokensYesThe `undoToken` from an earlier write’s successfully recorded undo receipt.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare destructiveHint=true and readOnlyHint=false; the description goes far beyond by disclosing token expiry (30 minutes, UTC), that a token reverses the entire change atomically (delete what it created, restore what it changed/removed), the `stale` failure mode when a touched row changed again, `conflictingRows` with reasons and a 50-row truncation flag, and newest-write-first ordering across multiple tokens.

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?

Front-loaded with the verb and the list of undoable operations; every sentence carries distinct information. It is dense and slightly run-on with stacked em-dashes, but nothing is redundant.

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?

No output schema exists, yet the description explains the return shape (per-token `results` counting `reverted`, `restored`, `removed`, `voided`) plus error semantics. For a destructive, single-parameter tool this is essentially complete.

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

Parameters4/5

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

Schema coverage is 100% so the baseline is 3, but the description adds real meaning: the token is the `undoToken` from a successful undo receipt, it works only before `expiresAt`, and multiple tokens need not be ordered. The maxItems=20 constraint is only in the schema.

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?

States a specific verb ('Undo — revert, roll back...') and enumerates exactly which prior operations it reverses: write_events/delete_events batches, review_day actions, manage_inbox calls, and manage_categories calls. An agent can distinguish it from every sibling without opening a schema.

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?

Explicitly states the precondition (pass the `undoToken` returned by those calls, only while active and before `expiresAt`) and names an alternative path: use review_day with action 'discard' to discard a whole day's reflection by date. Covers both when-to-use and when-to-use-something-else.

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

write_eventsWrite eventsInspect

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 by its ORIGINAL date, also after a move (the read's id and originalDate give it); 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. projectId links a live project (null on update clears it and keeps the area); a new project with no areaId gives the event the area of the project. priority is 0 none to 4 urgent. calendarId is the home calendar (omit = the default calendar, null = dial only) and mirrorCalendarIds the one-way copies; mirrorStyles sets a copy to 'private' or 'busy' (a shield that hides the details). A calendar's copyStyle in get_schedule integrations applies when mirrorStyles omits that calendar. Copies of a series need a home calendar. To find a conflict-free time for a create, read the day's freeSlots with get_schedule first. To place an existing Inbox item, use manage_inbox 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. conflictPolicy: "propose" means a write never overlaps a blocking event: it fails with conflict and nearestSlots; resend with one of those slots. Changes to a calendar-linked event also reach that calendar; don't edit an event marked readOnly (the tool refuses the change). To remove events or clear days use delete_events. The response has per-op results (each with its 0-based index), undoToken + expiresAt (UTC) when an undo receipt is recorded, and timezone when a result carries a span. Results read stored state after the batch commits; a later op can affect an earlier op’s returned event. A row with warnings: ["classification_pending"] may still get an eligible area, activity type, kind or energy settings from the AI after this reply. Native creates preserve the caller’s kind, including default blocking; AI does not change it. A client-minted create id must be a UUID.

ParametersJSON Schema
NameRequiredDescriptionDefault
opsYes
dryRunNoCheck the ops without a write: conflicts come back with `nearestSlots`, and each valid op comes back `skipped`.
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.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updates
    • Changedget_schedule3 fields changed
      • addedInput schema / properties / backlogMinPriority
        Added value: +{
        +  "description": "Filter the Inbox blocks to a priority of at least this value (0 none, 1 low, 2 medium, 3 high, 4 urgent). Needs includeBacklog: true; composes with the other filters.",
        +  "maximum": 4,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / backlogProjectId
        Added value: +{
        +  "description": "Filter the Inbox blocks to one project id, or \"none\" for the blocks with no project. Needs includeBacklog: true; composes with the other filters.",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / includeLookups / description
        Previous value: -"Default true. Pass false to leave out `areas`, `activityTypes` and `integrations` when you already have them from an earlier read."New value: +"Default true. Pass false to leave out `areas`, `activityTypes`, `projects` and `integrations` when you already have them from an earlier read."
    • Changedmanage_categories1 field changed
      • addedInput schema / properties / projects
        Added value: +{
        +  "items": {
        +    "oneOf": [
        +      {
        +        "additionalProperties": false,
        +        "properties": {
        +          "areaId": {
        +            "description": "The parent area id, or null for no area. When a write moves an Inbox item to the project and sets no area, the item takes this area.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "name": {
        +            "description": "The project name; unique among all live projects of the user, in any area.",
        +            "maxLength": 60,
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          "op": {
        +            "const": "create",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "op",
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "properties": {
        +          "archived": {
        +            "description": "true archives the project: it leaves the lookups and takes no new links, but its links stay. false restores it.",
        +            "type": "boolean"
        +          },
        +          "areaId": {
        +            "description": "The parent area id, or null for no area. When a write moves an Inbox item to the project and sets no area, the item takes this area.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "name": {
        +            "description": "The project name; unique among all live projects of the user, in any area.",
        +            "maxLength": 60,
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          "op": {
        +            "const": "update",
        +            "type": "string"
        +          },
        +          "order": {
        +            "description": "The sort position.",
        +            "type": "number"
        +          },
        +          "publishCalendarId": {
        +            "description": "The task list that a new Inbox item of this project is created in, unless the item names its own list. null turns it off.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "op",
        +          "id"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "The project to delete; its items and events keep their area and lose the project link.",
        +            "type": "string"
        +          },
        +          "op": {
        +            "const": "delete",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "op",
        +          "id"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "The shared project to split a link from.",
        +            "type": "string"
        +          },
        +          "linkId": {
        +            "description": "The task list (`source_calendars` id) or Linear project (`source_projects` id) that feeds `id` and moves to a new project of its own, \"{name} ({Provider})\".",
        +            "type": "string"
        +          },
        +          "op": {
        +            "const": "split",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "op",
        +          "id",
        +          "linkId"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "The live project that the Linear project feeds next.",
        +            "type": "string"
        +          },
        +          "linkId": {
        +            "description": "The Linear project (`source_projects` id) to point at `id`. Its Inbox items move along. A task list changes its project in its list settings.",
        +            "type": "string"
        +          },
        +          "op": {
        +            "const": "relink",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "op",
        +          "id",
        +          "linkId"
        +        ],
        +        "type": "object"
        +      }
        +    ]
        +  },
        +  "maxItems": 50,
        +  "type": "array"
        +}
    • Changedmanage_inbox1 field changed
      • changedInput schema / properties / ops / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "activityTypeId": {
        -        "description": "The activity type id. null or omitted leaves it unset.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "areaId": {
        -        "description": "The area id. null or omitted leaves it unset.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "calendarId": {
        -        "anyOf": [
        -          {
        -            "minLength": 1,
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "description": "The Source of each item: a writable task list to also create the item in, as an `id` from `get_schedule` `integrations.sources[].calendars[]` of a task source. null keeps the items in Reassign only. Omit it to use the account default (`defaultCalendarId`), which creates the task when it is a task list. On `capture_text`, an item goes to a list that the text explicitly names (\"add to Todoist Work: …\") instead."
        -      },
        -      "checklist": {
        -        "additionalProperties": false,
        -        "description": "The block's microtasks, in order — REPLACES the whole list (send every item you want kept; an empty `items` clears them). An Inbox block has no occurrence, so nothing is ticked off until it is scheduled.",
        -        "properties": {
        -          "items": {
        -            "items": {
        -              "additionalProperties": false,
        -              "properties": {
        -                "id": {
        -                  "description": "Keep an item id from a read; omit for a new item.",
        -                  "type": "string"
        -                },
        -                "text": {
        -                  "maxLength": 200,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            },
        -            "maxItems": 50,
        -            "type": "array"
        -          }
        -        },
        -        "required": [
        -          "items"
        -        ],
        -        "type": "object"
        -      },
        -      "durationMinutes": {
        -        "description": "Estimated length in whole minutes, 5 to 1440. Sizes the block when placed.",
        -        "maximum": 1440,
        -        "minimum": 5,
        -        "type": "integer"
        -      },
        -      "enrich": {
        -        "description": "Let AI clean this capture up before it is saved: propose a better name, estimate durationMinutes, and copy out any microtasks the captured text spells out. For RAW captures only — text grabbed off a web page, where the name is a paragraph rather than an intention. Do NOT set it for something the user typed or dictated: it may RENAME the block, and a name they chose must stand. Fields you send yourself always win; only the name can be replaced.",
        -        "type": "boolean"
        -      },
        -      "kind": {
        -        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit for \"blocking\".",
        -        "enum": [
        -          "blocking",
        -          "non_blocking",
        -          "reference"
        -        ],
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 200,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "notes": {
        -        "maxLength": 2000,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "capture",
        -        "type": "string"
        -      },
        -      "plannedDate": {
        -        "description": "The day this intention is planned for (still untimed — placing it on the dial is a separate `schedule`). Groups it under that day in the tray.",
        -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        -        "type": "string"
        -      },
        -      "plannedUntil": {
        -        "description": "Inclusive end of a planned window; it must fall after plannedDate.",
        -        "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"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "name"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "activityTypeId": {
        -        "description": "The activity type id. null or omitted leaves it unset.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "areaId": {
        -        "description": "The area id. null or omitted leaves it unset.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "calendarId": {
        -        "anyOf": [
        -          {
        -            "minLength": 1,
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "description": "The Source of each item: a writable task list to also create the item in, as an `id` from `get_schedule` `integrations.sources[].calendars[]` of a task source. null keeps the items in Reassign only. Omit it to use the account default (`defaultCalendarId`), which creates the task when it is a task list. On `capture_text`, an item goes to a list that the text explicitly names (\"add to Todoist Work: …\") instead."
        -      },
        -      "durationMinutes": {
        -        "description": "A length for every item. Omit it to keep the AI estimate; send it only when the user chose one.",
        -        "maximum": 1440,
        -        "minimum": 5,
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit for \"blocking\".",
        -        "enum": [
        -          "blocking",
        -          "non_blocking",
        -          "reference"
        -        ],
        -        "type": "string"
        -      },
        -      "notes": {
        -        "description": "Notes added to every item.",
        -        "maxLength": 2000,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "capture_text",
        -        "type": "string"
        -      },
        -      "plannedDate": {
        -        "description": "A planned day for every item. Omit it to keep the AI day.",
        -        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        -        "type": "string"
        -      },
        -      "plannedUntil": {
        -        "description": "Inclusive end of a planned window; it must fall after plannedDate.",
        -        "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"
        -      },
        -      "text": {
        -        "description": "What the user typed, dictated or selected, as is. AI splits it into 1 to 10 Inbox items, each with a short name, notes, a length and a day when the text names one. Without the AI the first line is the name and the rest are notes.",
        -        "maxLength": 2000,
        -        "minLength": 1,
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "activityTypeId": {
        -        "description": "The activity type id. null clears the link; omit to keep it.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "areaId": {
        -        "description": "The area id. null clears the link; omit to keep it.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "checklist": {
        -        "additionalProperties": false,
        -        "description": "The block's microtasks, in order — REPLACES the whole list (send every item you want kept; an empty `items` clears them). An Inbox block has no occurrence, so nothing is ticked off until it is scheduled.",
        -        "properties": {
        -          "items": {
        -            "items": {
        -              "additionalProperties": false,
        -              "properties": {
        -                "id": {
        -                  "description": "Keep an item id from a read; omit for a new item.",
        -                  "type": "string"
        -                },
        -                "text": {
        -                  "maxLength": 200,
        -                  "minLength": 1,
        -                  "type": "string"
        -                }
        -              },
        -              "required": [
        -                "text"
        -              ],
        -              "type": "object"
        -            },
        -            "maxItems": 50,
        -            "type": "array"
        -          }
        -        },
        -        "required": [
        -          "items"
        -        ],
        -        "type": "object"
        -      },
        -      "durationMinutes": {
        -        "description": "Estimated length in whole minutes, 5 to 1440. Sizes the block when placed.",
        -        "maximum": 1440,
        -        "minimum": 5,
        -        "type": "integer"
        -      },
        -      "id": {
        -        "description": "The Inbox block id (from the schedule read's `backlog`).",
        -        "type": "string"
        -      },
        -      "kind": {
        -        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit to keep it.",
        -        "enum": [
        -          "blocking",
        -          "non_blocking",
        -          "reference"
        -        ],
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 200,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "notes": {
        -        "maxLength": 2000,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "update",
        -        "type": "string"
        -      },
        -      "plannedDate": {
        -        "anyOf": [
        -          {
        -            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "description": "Set/move the block's planned day; null clears it back to Someday (also clears any window end). Google Tasks, Microsoft To Do and Linear sync this date both ways. Todoist dates must be changed in Todoist."
        -      },
        -      "plannedUntil": {
        -        "anyOf": [
        -          {
        -            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "description": "Inclusive end of a planned window; it must fall after plannedDate. null collapses the window to one day."
        -      },
        -      "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 block was captured from (http(s)); null clears the source chip."
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "description": "The Inbox block id to delete from the Inbox.",
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "remove",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "description": "The Inbox block id to place on the dial.",
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "schedule",
        -        "type": "string"
        -      },
        -      "recurrence": {
        -        "description": "Optionally make the placed block repeat, as an RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
        -        "type": "string"
        -      },
        -      "start": {
        -        "description": "Local start \"YYYY-MM-DDTHH:MM\"; the block's duration sizes it.",
        -        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id",
        -      "start"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "description": "The dial event id to move to the Inbox (from a schedule or search read). Must be a native or owned-calendar one-off that hasn't been reviewed.",
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "park",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "activityTypeId": {
        +        "description": "The activity type id. null or omitted leaves it unset.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "areaId": {
        +        "description": "The area id. null or omitted leaves it unset.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "calendarId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "The Source of each item: a writable task list to also create the item in, as an `id` from `get_schedule` `integrations.sources[].calendars[]` of a task source. null keeps the items in Reassign only. Omit it to use the default list of the item's project, else the account default (`defaultCalendarId`), which creates the task when it is a task list. On `capture_text`, an item goes to a list that the text explicitly names (\"add to Todoist Work: …\") instead."
        +      },
        +      "checklist": {
        +        "additionalProperties": false,
        +        "description": "The block's microtasks, in order — REPLACES the whole list (send every item you want kept; an empty `items` clears them). An Inbox block has no occurrence, so nothing is ticked off until it is scheduled.",
        +        "properties": {
        +          "items": {
        +            "items": {
        +              "additionalProperties": false,
        +              "properties": {
        +                "id": {
        +                  "description": "Keep an item id from a read; omit for a new item.",
        +                  "type": "string"
        +                },
        +                "text": {
        +                  "maxLength": 200,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            },
        +            "maxItems": 50,
        +            "type": "array"
        +          }
        +        },
        +        "required": [
        +          "items"
        +        ],
        +        "type": "object"
        +      },
        +      "durationMinutes": {
        +        "description": "Estimated length in whole minutes, 5 to 1440. Sizes the block when placed.",
        +        "maximum": 1440,
        +        "minimum": 5,
        +        "type": "integer"
        +      },
        +      "enrich": {
        +        "description": "Let AI clean this capture up before it is saved: propose a better name, estimate durationMinutes, and copy out any microtasks the captured text spells out. For RAW captures only — text grabbed off a web page, where the name is a paragraph rather than an intention. Do NOT set it for something the user typed or dictated: it may RENAME the block, and a name they chose must stand. Fields you send yourself always win; only the name can be replaced.",
        +        "type": "boolean"
        +      },
        +      "kind": {
        +        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit for \"blocking\".",
        +        "enum": [
        +          "blocking",
        +          "non_blocking",
        +          "reference"
        +        ],
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 200,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "notes": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "capture",
        +        "type": "string"
        +      },
        +      "plannedDate": {
        +        "description": "The day this intention is planned for (still untimed — placing it on the dial is a separate `schedule`). Groups it under that day in the tray.",
        +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +        "type": "string"
        +      },
        +      "plannedUntil": {
        +        "description": "Inclusive end of a planned window; it must fall after plannedDate.",
        +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +        "type": "string"
        +      },
        +      "priority": {
        +        "description": "0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit for 0.",
        +        "maximum": 4,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "projectId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "A live project id from get_schedule `projects`. When the project changes and the op sets no areaId, the item takes the area of the project, also over an area the user set by hand. On an item linked to a task, the task stays when its list (or Linear project) feeds the new project; else it moves to the one target of that project in the same account (for Linear: open, in the issue team). With 2 or more lists it goes to the \"New tasks go to\" list of the project. Any other case, and a move of a scheduled task, is refused with read_only. A clear is never refused. null or omitted leaves it unset."
        +      },
        +      "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"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "name"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "activityTypeId": {
        +        "description": "The activity type id. null or omitted leaves it unset.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "areaId": {
        +        "description": "The area id. null or omitted leaves it unset.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "calendarId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "The Source of each item: a writable task list to also create the item in, as an `id` from `get_schedule` `integrations.sources[].calendars[]` of a task source. null keeps the items in Reassign only. Omit it to use the default list of the item's project, else the account default (`defaultCalendarId`), which creates the task when it is a task list. On `capture_text`, an item goes to a list that the text explicitly names (\"add to Todoist Work: …\") instead."
        +      },
        +      "durationMinutes": {
        +        "description": "A length for every item. Omit it to keep the AI estimate; send it only when the user chose one.",
        +        "maximum": 1440,
        +        "minimum": 5,
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit for \"blocking\".",
        +        "enum": [
        +          "blocking",
        +          "non_blocking",
        +          "reference"
        +        ],
        +        "type": "string"
        +      },
        +      "notes": {
        +        "description": "Notes added to every item.",
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "capture_text",
        +        "type": "string"
        +      },
        +      "plannedDate": {
        +        "description": "A planned day for every item. Omit it to keep the AI day.",
        +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +        "type": "string"
        +      },
        +      "plannedUntil": {
        +        "description": "Inclusive end of a planned window; it must fall after plannedDate.",
        +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +        "type": "string"
        +      },
        +      "priority": {
        +        "description": "A priority for every item: 0 none, 1 low, 2 medium, 3 high, 4 urgent.",
        +        "maximum": 4,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "projectId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "A live project id for every item. When the op sets no areaId, each item takes the area of the project. null or omitted leaves it unset."
        +      },
        +      "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"
        +      },
        +      "text": {
        +        "description": "What the user typed, dictated or selected, as is. AI splits it into 1 to 10 Inbox items, each with a short name, notes, a length and a day when the text names one. Without the AI the first line is the name and the rest are notes.",
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "activityTypeId": {
        +        "description": "The activity type id. null clears the link; omit to keep it.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "areaId": {
        +        "description": "The area id. null clears the link; omit to keep it.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "checklist": {
        +        "additionalProperties": false,
        +        "description": "The block's microtasks, in order — REPLACES the whole list (send every item you want kept; an empty `items` clears them). An Inbox block has no occurrence, so nothing is ticked off until it is scheduled.",
        +        "properties": {
        +          "items": {
        +            "items": {
        +              "additionalProperties": false,
        +              "properties": {
        +                "id": {
        +                  "description": "Keep an item id from a read; omit for a new item.",
        +                  "type": "string"
        +                },
        +                "text": {
        +                  "maxLength": 200,
        +                  "minLength": 1,
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "text"
        +              ],
        +              "type": "object"
        +            },
        +            "maxItems": 50,
        +            "type": "array"
        +          }
        +        },
        +        "required": [
        +          "items"
        +        ],
        +        "type": "object"
        +      },
        +      "durationMinutes": {
        +        "description": "Estimated length in whole minutes, 5 to 1440. Sizes the block when placed.",
        +        "maximum": 1440,
        +        "minimum": 5,
        +        "type": "integer"
        +      },
        +      "id": {
        +        "description": "The Inbox block id (from the schedule read's `backlog`).",
        +        "type": "string"
        +      },
        +      "kind": {
        +        "description": "The kind the event takes when scheduled: \"blocking\" occupies time, \"non_blocking\" is an overlay that may overlap others, \"reference\" is something to see but not do. Omit to keep it.",
        +        "enum": [
        +          "blocking",
        +          "non_blocking",
        +          "reference"
        +        ],
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 200,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "notes": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "plannedDate": {
        +        "anyOf": [
        +          {
        +            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "Set/move the block's planned day; null clears it back to Someday (also clears any window end). Google Tasks, Microsoft To Do and Linear sync this date both ways. Todoist dates must be changed in Todoist."
        +      },
        +      "plannedUntil": {
        +        "anyOf": [
        +          {
        +            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "Inclusive end of a planned window; it must fall after plannedDate. null collapses the window to one day."
        +      },
        +      "priority": {
        +        "description": "0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit to keep it.",
        +        "maximum": 4,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "projectId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "A live project id from get_schedule `projects`. When the project changes and the op sets no areaId, the item takes the area of the project, also over an area the user set by hand. On an item linked to a task, the task stays when its list (or Linear project) feeds the new project; else it moves to the one target of that project in the same account (for Linear: open, in the issue team). With 2 or more lists it goes to the \"New tasks go to\" list of the project. Any other case, and a move of a scheduled task, is refused with read_only. A clear is never refused. null clears the project and keeps the area; omit to keep it."
        +      },
        +      "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 block was captured from (http(s)); null clears the source chip."
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "The Inbox block id to delete from the Inbox.",
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "remove",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "The Inbox block id to place on the dial.",
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "schedule",
        +        "type": "string"
        +      },
        +      "recurrence": {
        +        "description": "Optionally make the placed block repeat, as an RRULE (e.g. \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"). Omit for a one-off.",
        +        "type": "string"
        +      },
        +      "start": {
        +        "description": "Local start \"YYYY-MM-DDTHH:MM\"; the block's duration sizes it.",
        +        "pattern": "^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)$",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id",
        +      "start"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "description": "The dial event id to move to the Inbox (from a schedule or search read). Must be a native or owned-calendar one-off that hasn't been reviewed.",
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "park",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedwrite_events1 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 UUID event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
        -        "format": "uuid",
        -        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -        "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"
        -      },
        -      "mirrorStyles": {
        -        "additionalProperties": {
        -          "enum": [
        -            "full",
        -            "private",
        -            "busy"
        -          ],
        -          "type": "string"
        -        },
        -        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        -        "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"
        -      },
        -      "mirrorStyles": {
        -        "additionalProperties": {
        -          "enum": [
        -            "full",
        -            "private",
        -            "busy"
        -          ],
        -          "type": "string"
        -        },
        -        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        -        "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 UUID event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
        +        "format": "uuid",
        +        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +        "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"
        +      },
        +      "mirrorStyles": {
        +        "additionalProperties": {
        +          "enum": [
        +            "full",
        +            "private",
        +            "busy"
        +          ],
        +          "type": "string"
        +        },
        +        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "name": {
        +        "maxLength": 200,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "notes": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "create",
        +        "type": "string"
        +      },
        +      "priority": {
        +        "description": "0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit for 0.",
        +        "maximum": 4,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "projectId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "A live project id from get_schedule `projects`. When the project changes and the op sets no areaId, the event takes the area of the project. null or omitted leaves it unset."
        +      },
        +      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        +        "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"
        +      },
        +      "mirrorStyles": {
        +        "additionalProperties": {
        +          "enum": [
        +            "full",
        +            "private",
        +            "busy"
        +          ],
        +          "type": "string"
        +        },
        +        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "name": {
        +        "maxLength": 200,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "notes": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "priority": {
        +        "description": "0 none, 1 low, 2 medium, 3 high, 4 urgent. Omit to keep it.",
        +        "maximum": 4,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "projectId": {
        +        "anyOf": [
        +          {
        +            "minLength": 1,
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "description": "A live project id from get_schedule `projects`. When the project changes and the op sets no areaId, the event takes the area of the project. null clears the project and keeps the area; omit to keep it."
        +      },
        +      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        +        "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. 3 tool updates
    • Removedget_category_usage
    • Changedmanage_categories2 fields changed
      • changedInput schema / properties / activityTypes / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "create",
        -        "type": "string"
        -      },
        -      "pattern": {
        -        "description": "A fill pattern; omit to auto-pick.",
        -        "enum": [
        -          "solid",
        -          "hatch_r",
        -          "hatch_l",
        -          "cross",
        -          "horizontal",
        -          "vertical",
        -          "grid",
        -          "dots",
        -          "waves",
        -          "chevron"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "name"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "update",
        -        "type": "string"
        -      },
        -      "order": {
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "pattern": {
        -        "description": "A fill pattern; omit to auto-pick.",
        -        "enum": [
        -          "solid",
        -          "hatch_r",
        -          "hatch_l",
        -          "cross",
        -          "horizontal",
        -          "vertical",
        -          "grid",
        -          "dots",
        -          "waves",
        -          "chevron"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "delete",
        -        "type": "string"
        -      },
        -      "reassignTo": {
        -        "description": "Another activity type's id to move the linked events onto. Without it, the delete clears the type on those events.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "create",
        +        "type": "string"
        +      },
        +      "pattern": {
        +        "description": "A fill pattern; omit to auto-pick.",
        +        "enum": [
        +          "solid",
        +          "hatch_r",
        +          "hatch_l",
        +          "cross",
        +          "horizontal",
        +          "vertical",
        +          "grid",
        +          "dots",
        +          "waves",
        +          "chevron"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "name"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "order": {
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "pattern": {
        +        "description": "A fill pattern; omit to auto-pick.",
        +        "enum": [
        +          "solid",
        +          "hatch_r",
        +          "hatch_l",
        +          "cross",
        +          "horizontal",
        +          "vertical",
        +          "grid",
        +          "dots",
        +          "waves",
        +          "chevron"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "delete",
        +        "type": "string"
        +      },
        +      "reassignTo": {
        +        "description": "Another activity type's id to move the linked items onto, or null to clear their link. Required when items use it.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / areas / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "color": {
        -        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        -        "pattern": "^#[0-9a-f]{6}$",
        -        "type": "string"
        -      },
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "create",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "name"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "color": {
        -        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        -        "pattern": "^#[0-9a-f]{6}$",
        -        "type": "string"
        -      },
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "update",
        -        "type": "string"
        -      },
        -      "order": {
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "delete",
        -        "type": "string"
        -      },
        -      "reassignTo": {
        -        "description": "Another area's id to move the linked events onto. Without it, the delete clears the area on those events.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        +        "pattern": "^#[0-9a-f]{6}$",
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "create",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "name"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        +        "pattern": "^#[0-9a-f]{6}$",
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "order": {
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "delete",
        +        "type": "string"
        +      },
        +      "reassignTo": {
        +        "description": "Another area's id to move the linked items onto, or null to clear their link. Required when items use it.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedwrite_events1 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 UUID event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
        -        "format": "uuid",
        -        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -        "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        -        "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        -        "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 UUID event id, so the caller can read the new event back by a known id. Omit it and the server mints one.",
        +        "format": "uuid",
        +        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +        "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"
        +      },
        +      "mirrorStyles": {
        +        "additionalProperties": {
        +          "enum": [
        +            "full",
        +            "private",
        +            "busy"
        +          ],
        +          "type": "string"
        +        },
        +        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        +        "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"
        +      },
        +      "mirrorStyles": {
        +        "additionalProperties": {
        +          "enum": [
        +            "full",
        +            "private",
        +            "busy"
        +          ],
        +          "type": "string"
        +        },
        +        "description": "How much each copy shows, per copy calendar id: 'full' (default) copies the title and notes; 'private' keeps them but marks the copy private; 'busy' is a shield: a private copy with a neutral title (the calendar's busy title, else \"Busy\"), no notes, and no reminders. Each key must be in the event's mirrorCalendarIds. A calendar left out uses that calendar's default copy style. On update it REPLACES the map; {} clears it. Needs Reassign Pro; whole-series only.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "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 by its ORIGINAL date (the read's `originalDate`), also after the occurrence moved.",
        +        "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. 2 tool updates
    • Addedget_category_usage
    • Changedmanage_categories2 fields changed
      • changedInput schema / properties / activityTypes / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "create",
        -        "type": "string"
        -      },
        -      "pattern": {
        -        "description": "A fill pattern; omit to auto-pick.",
        -        "enum": [
        -          "solid",
        -          "hatch_r",
        -          "hatch_l",
        -          "cross",
        -          "horizontal",
        -          "vertical",
        -          "grid",
        -          "dots",
        -          "waves",
        -          "chevron"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "name"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "update",
        -        "type": "string"
        -      },
        -      "order": {
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "pattern": {
        -        "description": "A fill pattern; omit to auto-pick.",
        -        "enum": [
        -          "solid",
        -          "hatch_r",
        -          "hatch_l",
        -          "cross",
        -          "horizontal",
        -          "vertical",
        -          "grid",
        -          "dots",
        -          "waves",
        -          "chevron"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "delete",
        -        "type": "string"
        -      },
        -      "reassignTo": {
        -        "description": "Another activity type's id to move events onto; required if events still use this type.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "create",
        +        "type": "string"
        +      },
        +      "pattern": {
        +        "description": "A fill pattern; omit to auto-pick.",
        +        "enum": [
        +          "solid",
        +          "hatch_r",
        +          "hatch_l",
        +          "cross",
        +          "horizontal",
        +          "vertical",
        +          "grid",
        +          "dots",
        +          "waves",
        +          "chevron"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "name"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "order": {
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "pattern": {
        +        "description": "A fill pattern; omit to auto-pick.",
        +        "enum": [
        +          "solid",
        +          "hatch_r",
        +          "hatch_l",
        +          "cross",
        +          "horizontal",
        +          "vertical",
        +          "grid",
        +          "dots",
        +          "waves",
        +          "chevron"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "delete",
        +        "type": "string"
        +      },
        +      "reassignTo": {
        +        "description": "Another activity type's id to move the linked events onto. Without it, the delete clears the type on those events.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / areas / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "color": {
        -        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        -        "pattern": "^#[0-9a-f]{6}$",
        -        "type": "string"
        -      },
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "create",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "name"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "color": {
        -        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        -        "pattern": "^#[0-9a-f]{6}$",
        -        "type": "string"
        -      },
        -      "id": {
        -        "type": "string"
        -      },
        -      "name": {
        -        "maxLength": 60,
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "update",
        -        "type": "string"
        -      },
        -      "order": {
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "id": {
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "delete",
        -        "type": "string"
        -      },
        -      "reassignTo": {
        -        "description": "Another area's id to move events onto; required if events still use this area.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        +        "pattern": "^#[0-9a-f]{6}$",
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "create",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "name"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "color": {
        +        "description": "Lowercase \"#rrggbb\"; omit to auto-pick.",
        +        "pattern": "^#[0-9a-f]{6}$",
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "name": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "update",
        +        "type": "string"
        +      },
        +      "order": {
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "id": {
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "delete",
        +        "type": "string"
        +      },
        +      "reassignTo": {
        +        "description": "Another area's id to move the linked events onto. Without it, the delete clears the area on those events.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "id"
        +    ],
        +    "type": "object"
        +  }
        +]

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A productivity coaching assistant designed for ADHD support that provides intelligent task management, goal tracking, and personalized recommendations. It utilizes a persistent memory system to learn user patterns and preferences, helping to reduce decision paralysis through actionable suggestions.
    28
    1
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    A privacy-first, local-first MCP server that provides 15 ADHD/second-brain tools for capturing, prioritizing, and resurfacing tasks with context from calendar, mail, and messages.
    1
    -
  • F
    license
    B
    quality
    D
    maintenance
    An ADHD-friendly productivity system that uses AI to provide frictionless capture of tasks and ideas through natural language input, with automatic context detection and intelligent routing to appropriate project trackers. Eliminates cognitive overhead by working with ADHD thinking patterns rather than against them.
    3
    11
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.