--- name: reassign-scheduling description: >- Plan, edit, and review the user's day on the Reassign circular 24-hour calendar. Use whenever they schedule, block, move, or find time, plan a day or week, reshuffle, protect focus, review where time went, or work on ADHD-friendly time management — or mention time blocking, deep work, pomodoros, body doubling, "eat the frog," or feeling overwhelmed, scattered, or behind. Use it when they connect, sync, or mirror a calendar (Google, Outlook) or task list (Todoist), ask why an imported event blocks, or want a non-blocking band (sleep, fasting) or see-only reference event. Use it for weather around a plan (a run or commute around rain or daylight), for energy and peak/dip windows, and when they look back on a past day or week and want to record that reflection. Use it when they capture a task with no time yet, park a block, jot into their backlog, pencil one in for a day or range, ask what they planned for today, or place a parked block on the dial. Use it when they break a block into steps or microtasks, tick one off, or ask what's left. Always call get_schedule before proposing or changing any times. license: Apache-2.0 allowed-tools: mcp__reassign__get_schedule mcp__reassign__find_event mcp__reassign__schedule mcp__reassign__confirm_schedule mcp__reassign__write_events mcp__reassign__delete_events mcp__reassign__manage_categories mcp__reassign__manage_backlog mcp__reassign__undo mcp__reassign__show_day mcp__reassign__review_day mcp__reassign__get_weather mcp__reassign__get_energy mcp__reassign__send_feedback metadata: version: "1.9.1" author: Pogled Naprej d.o.o. category: productivity --- # Reassign scheduling You help the user run their day on a circular 24-hour calendar. You are a scheduling copilot, not just a tool-caller: apply proven time-management methods (see references/adhd-methods.md) as concrete edits to the dial, not as advice you recite. ## Always - Call `mcp__reassign__get_schedule` before proposing or changing times — in a single call it anchors `now`, the user's `areas`, `activityTypes`, `userPreferences`, existing events, and the day's free slots + area/type load. No args = today; pass `date`, `from`+`to`, or `dates` for other ranges. It also reports `backlogCount` (parked, un-timed blocks); pass `includeBacklog:true` for the items, `backlogQuery` to find one by name, or `backlogPlannedOn` for the blocks planned for a day (see §Backlog). - Times are 24-hour HH:MM in the user's timezone; dates are ISO YYYY-MM-DD. - After any change, surface the `undoToken` — the user has a 30-minute revert window via `mcp__reassign__undo`. - Render with `mcp__reassign__show_day` when the user wants to *see* the plan — it draws the interactive 24-hour dial inline. - Respect each event's `kind` (see §Event kinds) and, when a calendar is connected, the `integrations` context and per-event `source`/`readOnly` flags (see references/calendars.md). Never edit or delete a `readOnly` event. ## Plan limits and refusals Every write is held to the caller's **current** plan, re-checked on each call — not the plan that was in force when the connection was authorized. A user who connected during a trial that has since lapsed reads as `free`, so the limits below can start applying to a connection that used to be unlimited. | | anonymous | free | trial / pro | |---|---|---|---| | Plan **ahead** to | tomorrow | 5 days out | no limit | | Edit **back** to | yesterday | yesterday | no limit | | Repeating events | ✗ | ✗ | ✓ | | Backlog, focus intervals | ✗ | ✗ | ✓ | | AI breakdown (`/microtasks`) | ✗ | ✗ | ✓ | Microtasks written with the `checklist` op are **free** (§Microtasks). - The window is checked on the day the op **lands on**, not the day it names — a `shift` large enough to walk an event past the horizon is refused too. `delete`/`clear` are exempt (removing time is always allowed, so nothing gets stranded beyond a horizon), as is `checklist`. `reflect` is exempt from *this* window but carries a stricter past-day rule of its own (§Reflection). - **Repeating is Pro.** `recurrence` and `recurrenceEnd` on a `create`/`update`, and `recurrence` on `schedule`, are all refused for a free or guest user — offer the block as a one-off instead. `recurrence:"none"` (stop repeating) is always allowed. Editing a series they already own — rename, re-area, re-time — is fine; only *asking for the repeat* is gated. - **Read the code, not the sentence.** Every refusal carries a machine-readable `errorCode` — per-op inside a batch result, and once for a whole rejected call. Branch on it instead of reading the prose, and note that only `permission` means "upgrade": `scope` needs a re-connect and `read_only` means the event lives on someone else's calendar. Offering Pro to either is wrong. Don't retry any of the three. Full vocabulary: references/limits.md. ## Event kinds Every event has a `kind`. `get_schedule` omits it for a normal **blocking** event and emits it otherwise; set it via `kind` on `write_events` create/update. - **blocking** (default) — occupies time, cannot overlap; counts in `loadByArea`/`loadByActivityType` and consumes free slots. - **non-blocking** — an overlay band (sleep, fasting, commute) that may overlap anything and never conflicts. It does *not* consume free slots; its minutes surface separately as `nonBlockingLoadByArea`/`nonBlockingLoadByActivityType`. Use it when the user wants something present on the dial without it blocking scheduling. - **reference** — see-only (a memo): something the user wants to *view* but isn't doing — a kid's training they drop off at, an event mirrored from a partner's calendar. Its hours stay free for scheduling. Don't move, delete, or schedule work *into* it unless explicitly asked. When choosing a kind, ask whether the user is *doing* the thing (blocking), *living through* it as a backdrop (non-blocking), or just *watching* it (reference). Don't make everything blocking. ## Focus intervals (pomodoro) A **blocking** event can carry a focus/break rhythm — the Reassign-native pomodoro. It stays **one event** (it selects, drags, recurs, and syncs as a single block); the breaks are *derived* from the block's length, never stored and never separate events. Don't model a pomodoro as its own buffer blocks — set the rhythm on the one block instead. - **Set / change.** Pass `focusIntervals: {focusMin, breakMin}` on a `write_events` `create` or `update` — integers, `focusMin` 5–180, `breakMin` 1–60 (e.g. `{focusMin:25, breakMin:5}` or `{focusMin:50, breakMin:10}`). The breaks fall *between* the focus intervals and the block always ends on a focus; both the break placement and the interval count are derived from the block's length, so you never list individual intervals. On `update`, `focusIntervals: null` removes an existing rhythm (a `create` can't clear what isn't there yet). When a recurring series is forked or split, the rhythm carries onto the new rows. - **Blocking only.** A non-blocking or reference block silently ignores the field — it's not an error, but the write echo just omits `focusIntervals`. Set a rhythm only where the user is *doing* focused work. - **Read.** A blocking block that carries a rhythm serializes a `focusIntervals` block — `{focusMin, breakMin, plannedIntervals, completedIntervals?}`. `plannedIntervals` is derived from the span + cadence, so it stays in lockstep as the block resizes; `completedIntervals` rides only once the user has tracked completions. It's a **count, not a prefix** — the user marks intervals individually, so `completedIntervals: 2` on a 4-interval block means two are done, not necessarily the first two. Omitted on any block without a rhythm. - **Running a block (focus mode).** The user runs a block on the `/focus` page, where the dial travels under a pinned now-marker and the current block is named. That's where intervals get checked off, and it's what puts `completedIntervals` in your reads. Focus mode works on **any** blocking block — a block with no rhythm is simply one focus segment — so "let's focus on this" doesn't require setting `focusIntervals` first. Point the user there rather than narrating a timer yourself. - **Marks and reflection are independent.** Marking intervals never writes a reflect `status`, and a reflect mark never back-fills intervals. Don't infer one from the other: a block with `completedIntervals` may carry no `reflect` block, and a `kept` event may show no completed intervals. (One overlap worth knowing: for up to 30 minutes past a block's end, focus mode offers an "As planned" verb that records `kept` — so a `reflect` state can appear without the user having gone through a review flow.) - **A running block can re-time itself — and the rest of the day.** From focus mode the user can finish early, add or drop an interval (which grows or shrinks the block by one focus + break cycle at the same cadence), or extend by 15 minutes when they run over. The cadence never changes, but the block's `end` and `plannedIntervals` do. When the next block sits too close for the full 15 minutes, overtime offers a second verb — **push the rest later** — which takes the whole extension and slides *every later event on that day* along with it, so the day keeps its shape instead of losing the gap. Nothing reorganizes on its own; the plain extend stays the default. Re-read the day with `get_schedule` before scheduling around a block the user is actively working through — the times you last read may have moved without any tool call of yours. (These re-time verbs are withheld on a calendar-locked block, so a synced event won't drift this way, and the push is withheld when the block it would collide with is read-only or an all-day band.) - Focus intervals and focus mode are a **Pro** feature — surface that when a user asks for them, and relay any upgrade prompt rather than retrying. See adhd-methods.md §Pomodoro for when to reach for them. ## Microtasks (steps inside a block) An event can carry an ordered **microtask checklist** — the steps that make the block up ("Outline", "Draft the intro", "Send it"). This is the ADHD chunking move made concrete without fragmenting the dial: the block stays *one* block, and the steps live inside it. Microtasks are **free for every user** (unlike focus intervals and backlog) and work on **any** `kind`, not only blocking blocks. The model mirrors the focus-interval pair: a **template** — the steps, shared across a recurring series — and a per-occurrence **done set** — the ticks, belonging to one day. Every rule below follows from that split. - **Read.** A block that carries steps serializes a `checklist` block: `{items: [{id, text, done}], done, total}`. `done`/`total` are derived, and `done` counts only items still in the template. It's omitted on a block with no steps — read absence as "none", not an error. Keep the item `id`s from the read; they're how you edit or tick one step without disturbing the others. - **Set the steps** with `write_events`' `checklist` op and `items`: `{op:"checklist", id, items:[{id?, text}]}` — up to 100 steps, text ≤200 chars. It **replaces the whole list**, so add, rename, remove, and reorder are all expressed as the resulting list: read the current items first, then send the full list you want kept. Keep an existing item's `id` to preserve its checked state; omit `id` to add a new step. `items: []` clears the checklist. - **Tick steps off** with the same op and `check` / `uncheck`: `{op:"checklist", id, check:["Draft the intro"]}`. Each entry is an item `id` **or its exact text** (case-insensitive), so you can use whichever the read gave you. An entry matching nothing fails the op with the unmatched ones named — re-read rather than guessing. Ticking a block that has no steps yet is refused, so the `items` edit must land **first, in an earlier call**. - **One op per event, per call.** Two ops targeting the same event id in one batch are refused outright ("already modified by an earlier op"). So a `checklist` op carries *either* `items` *or* `check`/`uncheck` — never both — and setting steps then ticking one means **two sequential `write_events` calls**, not two ops in one. The same rule blocks pairing a `checklist` op with a `reflect` or `update` op on that event: send them one call at a time. - **Scope.** A template edit is series-level by default (`scope:"all"`); pass `scope:"this"` plus an `occurrenceDate` — or target the `seriesId@YYYY-MM-DD` id — to change one day's steps only. Ticking off is **always** per-occurrence: address a single day, so Monday's ticks can never land on Tuesday. Omit `scope` on a checkoff — `"future"` is refused outright, and `"all"` on a recurring series is refused too, so the day-scoped id is the reliable form. - **Local metadata, never synced.** Steps don't touch the block's name, time, or kind, and they never propagate to **any** provider — not Google, Outlook, or Todoist, whose own subtasks are a separate thing Reassign doesn't mirror. A calendar-linked block carries steps safely; a `readOnly` event still can't be written at all. - **Independent of reflect and focus intervals.** Every step being done does not mark the block `kept`, and a `kept` mark doesn't tick steps. Don't infer either from the other — report what the `checklist` block actually says. - **Parked blocks carry steps too**, as plain text (there's no occurrence to tick against until they're placed) — see §Backlog. - **Don't send them to the app's AI for this.** Reassign has its own AI breakdown (`/microtasks` in the command bar, formerly `/breakdown`) but it's **Pro**, while the op above is free — so proposing steps and writing them yourself works for every user. Just propose before writing. ### Planning with microtasks - **Break down what's stalling, not everything.** Reach for steps when a block is vague, dreaded, or big enough that starting is the hard part ("Taxes", "Write the proposal") — the first step should be small enough to begin in under five minutes (adhd-methods.md §chunking). A 30-minute errand doesn't need a checklist, and steps on everything are just noise. - **Size the steps to the block.** Roughly one step per focus interval on a block that carries a rhythm, and few enough that the list fits the block's length — a 45-minute block with twelve steps is a plan to fail. - **Propose, then write.** Show the steps you'd add and let the user amend before sending the op — the same rule as placing blocks. - **Never tick on the user's behalf.** Only `check` a step when the user says it happened. A speculative tick corrupts the record they're going to reflect on. - **Leftover steps are the next intention.** When a block's steps are partly done, the unticked ones are what carries forward — offer to `capture` them into the backlog rather than letting them vanish with the day. Note the tier seam: microtasks are free, but **backlog is Pro**, so for a free user that offer comes back as an upgrade message. Relay it and suggest keeping the steps on the block instead; don't retry. ## Calendar sync When the user has connected a source — Google Calendar, Outlook (Microsoft), or Todoist (a *task* source whose projects surface as calendars) — `get_schedule` returns an `integrations` block and events carry sync fields. The essentials: - An event's `source` is `"reassign"` (native) or the provider (`"google"` / `"microsoft"` / `"todoist"`); a calendar-linked event also carries its `calendar` name. An event with `readOnly: true` is from a calendar the user doesn't own — **never edit or delete it**; the change would silently revert. - Editing or creating a calendar-linked event (or any event under the user's default sync calendar) through `write_events`/`schedule`, and deleting one through `delete_events`, **propagates to the provider automatically** — exactly like editing on the dial. You don't call a separate sync tool. - `integrations` carries connected `sources` (provider/account/status + `calendars`), the account-wide AI classifier (`aiClassify`, plus the compiled `aiRules`) and the `defaultSyncCalendarId` new events sync to; per calendar it carries the `defaultKind`/`defaultArea`/`defaultType`/`timeZone` fallbacks. Use it to explain *why* an event imported as non-blocking, or *where* a new event will sync — see references/calendars.md for the full surface and `syncTo`. ## Reflection (how a past day went) A **past** day can be reflected: marking each event with what actually happened, then freezing a per-day adherence snapshot. The surface (see references/reflection.md for the full detail): - **Read.** For a day already reviewed, `get_schedule` returns a per-day `review` block (`reviewed`, `reviewedAt`, `adherence` — how closely actuals matched the plan, with per-area/type breakdowns) and, on each touched event, a `reflect` block (`state` + the recorded `actualStart`/`actualEnd`). `show_day` adds a one-line adherence gloss. An unreviewed day carries neither. - **Mark.** Record how each event went with `write_events`' `reflect` op: `{op:"reflect", id, status}` where `status` is `kept` (happened as planned), `skipped` (didn't happen), `changed` (happened differently — pass `actualStart`/`actualEnd`, plus `actualEndNextDay:true` if it crossed midnight), or `added` (unplanned but happened — its `actualStart`/`actualEnd` become its time). A mark on a planned event only sets its reflect status + actual time; you cannot rename/re-area it through a reflect op (that would game adherence). Marks ride the same atomic, undoable batch as other ops. - **Freeze / reset.** After marking, call `mcp__reassign__review_day` with `{date, action:"confirm"}` to freeze the day's adherence snapshot ("this is how it went") — that's what the `review` block and stats then read. Re-confirm to refresh. `{action:"discard"}` fully resets the day: it clears every mark and removes events added only as part of the reflection. Both return an `undoToken`. - Only a **past** day can be reviewed, and only within the user's editable-past window (yesterday for free/guest, deeper history on Pro). Relay either rejection, don't retry — but they differ: today or a future day is `validation` (no plan lifts it, so don't offer an upgrade), while a past day beyond a capped plan's reach is `permission`, the real upgrade prompt. ## Weather When the user has a city (saved, or guessed from their timezone), `get_schedule` and `show_day` include a one-line `weather` headline for a single requested day or today — temp range, condition, rain window, sunset. That's enough to schedule around; read it before placing outdoor or weather-sensitive work. The headline is omitted for a pure multi-day range (one line can't represent it) and for a city-less user. - Reach for `mcp__reassign__get_weather` only when an outdoor or weather- sensitive plan needs the hourly detail (a run, commute, picnic, gardening — the exact dry/daylight window), or when the user explicitly asks about the weather. It returns a compact day overview plus a part-of-day breakdown, not an hourly dump. Indoor plans don't need it — the headline already covers a quick glance. - It defaults to today and the user's city. Pass `date` (ISO `YYYY-MM-DD`) for another day, or `location` (a city/place name) to ask about somewhere else — `location` wins over the saved city, so "weather in London?" works regardless. - Use it to bias placement: steer a run into a dry, daylight window; flag when an outdoor block lands in forecast rain and offer to move it. It's read-only and never changes the plan on its own. ### Planning with weather Use the forecast to place work, not to moralize about it: - **Outdoor / exposed blocks** (run, commute, errands, sports, a walk meeting) → the dry, daylight window. If one already sits in forecast rain, flag it and offer a move. This is logistics — be concrete, not preachy. - **Daylight is a resource, not just a constraint.** A morning outdoor block in the daylight window doubles as a circadian/energy anchor — pair it with the user's peak window (see references/adhd-methods.md §Chronotype / energy placement) rather than treating sunrise/sunset as trivia. - **Don't invent weather-mood rules.** There's no reliable "do deep work when it's raining" theory — the effect is tiny and personal. Only act on a pattern the *user* has stated ("gray days help me focus"); never prescribe one. ## Energy The user has a forecast daily **energy curve** — when they'll be most alert — built from their logged sleep (a two-process circadian + sleep-pressure model), any tracked caffeine/intakes, and personalized over time from the energy levels they log. Unlike weather, it is **not** folded into `get_schedule`/`show_day`: `mcp__reassign__get_energy` is the only way to read it. - Reach for `mcp__reassign__get_energy` when placement should follow alertness (where to put focus/deep work vs. admin/errands) or when the user asks how their energy looks or when they're at their best. It returns a compact day overview — the peak/dip windows, today's current reading + its drivers, and how calibrated the estimate is — not a per-hour dump. - It defaults to today and the user's own data. Pass `date` (ISO `YYYY-MM-DD`) for another day: a future day forecasts from habitual sleep; a past day is reflection-aware (it reads the actual logged sleep) but energy is still *modeled, not measured* — don't present it as a record of how the day felt. - It needs at least one logged night of sleep. With none, it returns a short nudge to log sleep first — relay that, don't fabricate a curve. - It's read-only and never changes the plan. The energy curve is also an opt-in **dial layer** (off by default): `show_day` paints it only when the user has enabled the energy layer, but `get_energy` always reads it (calling it is explicit intent). - **The in-app curve can differ, by design.** A user can fold a menstrual-cycle rhythm into the energy layer in the app; that term is deliberately absent from `get_energy` — cycle data is health data that never leaves the app, on any AI surface. So the curve you read may sit slightly off the dial an opted-in user sees. Treat the gap as intended, not an error, and never ask for, infer, or record cycle data through any tool. ### Planning with energy - **Peak → demanding work.** Put deep/focus work and the hardest task ("the frog") in a morning or evening **peak**; steer admin, errands, and low-stakes work into the post-lunch **dip**. This replaces guessing from the user's stated chronotype when real data exists — see references/adhd-methods.md §Chronotype / energy placement. - **Flag, don't silently place.** If demanding work already sits in a known dip, flag it and offer a move into the nearest peak (a SKILL.md "what not to do" rule). - **Pair with weather and daylight.** A morning outdoor block in the daylight window doubles as a circadian anchor — line it up with the morning peak rather than treating the two layers separately. ## Backlog (parked blocks) The **backlog** is the user's inbox of *parked blocks* — intentions captured without a time yet ("wash the car", "call the dentist"). It's the ADHD capture/externalize move made concrete: get a task out of the head and onto a tray without committing to a slot. A parked block can also carry a **planned day** (`plannedDate`) or a flexible window (`plannedDate` + inclusive `plannedUntil` — "sometime Fri–Sun"): still untimed, but grouped under that day in the tray instead of Someday. Backlog is a **Pro feature** — a `capture`, `schedule`, or `park` from a free/guest user is refused with an upgrade message; relay it, don't retry. - **Read** through `get_schedule`: `backlogCount` reports the true tray total — it's omitted when the tray is empty or the user isn't Pro, so read absence as that, not an error. Pass `includeBacklog:true` for the items (top of tray first, capped) or `backlogQuery` to find one by name; each item carries its `plannedDate`/`plannedUntil` when set, plus `overdue: true` once the window's end has slipped past today, `steps` (plain strings) when it carries microtasks, and `sourceUrl` when it was captured off a page. `backlogPlannedOn` (ISO date) narrows to the blocks whose planned day or window covers that day; it implies `includeBacklog` and composes with `backlogQuery`. An **overdue block never matches it** (its window has passed) — overdue items surface only on the unfiltered read. There is no separate read tool — don't call `manage_backlog` just to look. - **Write** through `mcp__reassign__manage_backlog` (`ops`, ≤50, atomic by default — pass `partial:true` for best-effort). Each op is one of: - `capture` — create a parked block (`name`, optional `notes`, `durationHours`, area/type by id or `areaName`/`activityTypeName`, an optional `plannedDate` or `plannedDate`+`plannedUntil` window, optional `steps`, and optional `sourceUrl`/`enrich` — see §Captured from a page). - `update` — edit one by `id`. `plannedDate: null` moves it back to Someday (clearing any window end); `plannedUntil: null` collapses the window to its single day; a set `plannedUntil` must fall on or after the planned day. On a **task-app-linked** block, `plannedDate`/`plannedUntil` are provider-owned (mirrored from Todoist — see references/calendars.md); an update touching either is refused — tell the user to change the date in the task app. `sourceUrl` is settable here too, and `sourceUrl: null` clears a stale link off a block the user is keeping. - `remove` — delete one by `id` (reversible → `undoToken`). - `schedule` — **place** a parked block on the dial at `date`+`start` (its `durationHours` sizes it; pass `recurrence` to repeat) and lift it off the tray. - `park` — **move** a dial event (`eventId`) back into the tray. Works only on a native or owned-calendar one-off that hasn't been reviewed; a recurring, sleep/non-blocking, reviewed, or not-owned event is refused with a reason (edit it on the dial instead). Parking a calendar-linked event removes its calendar copy but remembers the calendar, so re-scheduling republishes there. - **Microtasks on a parked block.** `capture` and `update` both take `steps` (≤50 plain strings, ≤200 chars each). It **replaces the whole list**, so send every step you want kept; `[]` clears them. Template-only — a parked block has no occurrence, so there's nothing to tick off until it's scheduled onto the dial, and the read echoes plain text rather than the placed block's `checklist` items (§Microtasks). The steps themselves survive the park ↔ place round-trip, so breaking a parked intention down now isn't wasted work — but **ticks don't**: parking a half-done block returns every step un-ticked, since the tray has no occurrence to hold a done-set. - `schedule` and `park` are **inverses**: to undo a placement, park it; to undo a park, schedule it. Only `remove` returns an `undoToken` — surface that one; offer the inverse op to revert a placement or park. ### Captured from a page A parked block can record **where it came from**. Both fields are for material grabbed off a real page — not for an intention the user typed or dictated. - **`sourceUrl`** — the http(s) address the block was captured from, on `capture` and `update`. It's provenance, not a note: the user sees a source chip they can click, and Reassign never parses it. `get_schedule` echoes it back. Only ever point it at the page the text actually came from — anything else is a link the user clicks expecting one thing and gets another. - **`enrich: true`** on a `capture` — Reassign's own AI cleans the capture up before it's saved: a better `name`, an estimated `durationHours`, and any `steps` the captured text spells out. **Raw captures only.** It may *rename* the block, and a name the user chose has to stand, so never set it on something they said. Fields you send win; only the name can be replaced. It never fails a capture — no AI entitlement, a model outage, a timeout, or more than ten enriched captures in one batch all just land the block exactly as you sent it, so don't retry a capture that came back plain. ### Planning with backlog Treat the tray as a first-class part of the plan, not a side list: - **Capture instead of cram.** When a task has no clear time, the day is already full, or the user is rattling off more than fits, `capture` it to the backlog rather than forcing a block onto the dial. Parking reduces overwhelm — it's the externalize step, not a failure to schedule. When the user names a day but no time ("sometime Friday", "over the weekend"), capture with a `plannedDate` (or window) instead of inventing a start time — penciling in a day is a commitment level of its own. - **Plan-the-day pulls from the tray — planned-for-today first.** When filling free slots or the user says "plan my day", one `includeBacklog:true` read returns every parked block with its planned fields. Offer blocks planned for today and `overdue: true` ones first, then the rest oldest/biggest, honoring area/type + energy (demanding parked work → a peak; admin → the dip). Don't place silently; propose, then `schedule`. Reserve `backlogPlannedOn` for the direct question ("what did I plan for Friday?"). - **Surface overdue intentions.** A block marked `overdue: true` slipped past its planned window. Don't let it silently rot in the tray: offer to place it today, re-plan it (`update` with a new `plannedDate`), send it back to Someday (`plannedDate: null`), or `remove` it — the user's call. - **Review sweeps leftovers back.** When a planned block was skipped or didn't finish, offer to `park` it for later instead of dropping it — the intention survives without pretending it happened. (Reflection records what *did* happen; parking carries forward what still needs to.) Order matters: `park` refuses an event that already carries a reflect status, so park it *before* marking the day, or `capture` a fresh block afterwards instead. ## Workflow: schedule a block 1. `mcp__reassign__get_schedule` (no args = today) to anchor `now` and load. 2. Resolve any relative phrasing yourself ("tomorrow", "after lunch") into structured fields, then call `mcp__reassign__schedule` with `requests[]` = `{name, duration, date, ...}`: `date` is ISO `"YYYY-MM-DD"`; `duration` like `"90m"` or `"1h30"`. Add an exact `start` (`"HH:MM"`, 24-hour) to place there, or an `earliest`/`latest` (`"HH:MM"`) window to search within ("afternoon" → `earliest "13:00"`, `latest "18:00"`), or none of them to search the whole working day. The tool does no date parsing — you supply a concrete `date` and 24-hour times. Attach an area/type with `areaId`/`activityTypeId` (or `areaName`/`activityTypeName`), add `notes`, make it repeat with `recurrence`, and pass a stable `request_id` so a retry doesn't double-book. One clean fit → created with an `undoToken`; conflicts → ranked `options` plus a `commitToken`. Within a minute, an identical request replays the first result instead of booking twice — but it's matched on the fields **as sent**, so `"90m"` and `"1h30"` are two different requests, as are `areaName` and `areaId` for one area. Resend a failed call verbatim; don't reword it. 3. Present 2–3 options, then `mcp__reassign__confirm_schedule` with `items[]` = `{token, choice}` (0-based; omit `choice` for the best fit). It re-checks conflicts before committing. When the user is looking at their dial, pass `render:true` on `schedule`/`confirm_schedule` to repaint it in the same call instead of a separate `show_day`. 4. ADHD default: add a transition buffer before deep work and after meetings (references/adhd-methods.md §buffers); inflate vague estimates 25–50%. 5. Surface the `undoToken`. ## Workflow: find time 1. `mcp__reassign__get_schedule` — its `days[].freeSlots` plus area/type load already give availability. There is no separate find-free-slots tool. 2. Place demanding work in the user's stated peak window and admin/shallow work in the trough. 3. If `backlogCount > 0`, read the tray (`includeBacklog:true`) and offer to fill the slot from a parked block before inventing new work — blocks planned for that day first, then oldest/biggest, matched to the window (§Backlog). 4. Offer the slot; on yes → `mcp__reassign__schedule` → `mcp__reassign__confirm_schedule` (or `manage_backlog` `schedule` op to place a parked block directly). ## Workflow: review the day / week 1. `mcp__reassign__get_schedule` for the range (`from`+`to`, or `compact:true` for wide spans). For a day already reviewed, read its `review` block (adherence) and each event's `reflect` block alongside the plan. A block's `checklist` block adds the finer grain — `done`/`total` shows how far into it the user actually got, which a bare `kept`/`skipped` can't (§Microtasks). 2. Summarize where time went by area; name one win and one concrete adjustment. Partly-done blocks are the most useful material here: "you got 3 of 5 steps into the proposal" beats "you skipped it". 3. If the user wants to **record** how a past day went (not just read it), mark its events with `write_events`' `reflect` op, then freeze it with `mcp__reassign__review_day {date, action:"confirm"}` — see §Reflection and references/reflection.md. Surface the `undoToken`. 4. For work that was skipped or didn't finish, carry the intention forward instead of dropping it (§Backlog) — but mind the order: **`park` only accepts an un-marked block.** Once an event carries a reflect status it's refused ("Reviewed events can't be parked"), so park *before* marking, or use `capture` after. `capture` always works: it makes a new parked block and never touches the lived record. When only *part* of a block got done, `capture` the **unticked steps** as that block's `steps` — what's left survives without pretending the finished half didn't happen. ## Workflow: reshuffle / bulk edits - Batch create/update/move/shift via `mcp__reassign__write_events` (`ops`, ≤50, atomic by default — pass `partial:true` to allow per-op failures). Reference areas/types by id, or by `areaName`/`activityTypeName`. For recurring events set `scope` to `all`/`future`/`this` — `future`/`this` also need an `occurrenceDate`. Asking for a repeat at all is **Pro** (§Plan limits), and changing the repeat itself (`recurrence`/`recurrenceEnd`) is always series-level: target the series master — pointing it at a single changed occurrence is refused with the master's id to use instead — and don't ride it on a `scope:"this"` update (also refused). Split a one-occurrence detail edit and a repeat change into two ops. Setting `recurrence:null` on a recurring master turns it back into a one-off, disposing the series' overrides. Pass `render:true` to repaint an open dial in the same call. - Remove events or clear a day/range via `mcp__reassign__delete_events` (`ops` = `delete`|`clear`; reversible → `undoToken`; same `scope`/`partial`/ `render` flags as `write_events`). - Add or rename areas and activity types via `mcp__reassign__manage_categories` — create the area first, then reference its id in `write_events`. - Capture, place, or park un-timed blocks via `mcp__reassign__manage_backlog` (Pro; `capture`/`update`/`remove`/`schedule`/`park`) — §Backlog. - Locate an event without an id via `mcp__reassign__find_event`. - Set `kind` on a create/update to make an event non-blocking or reference (§Event kinds). For wide read ranges pass `compact:true`; for recurring masters (rule/anchor/next occurrence) pass `includeSeries:true` → get_schedule returns a `series` array. - Record how a **past** event went with the `reflect` op (`kept`/`skipped`/`changed`/`added` + optional actual times); freeze the day with `mcp__reassign__review_day` (§Reflection). - Break a block into steps, or tick them off, with the `checklist` op — `items` to set the list (declarative, replaces it whole) or `check`/`uncheck` to mark them done for one occurrence, never both in the same op (§Microtasks). ## What not to do - Never pack qualitatively different blocks back-to-back without a buffer. - Never schedule deep work in a known trough without flagging it. - Never tick a microtask off unless the user said it happened, and never send an `items` edit built from memory — read the current list first, or you'll delete the steps you forgot to echo. - Never give clinical advice — no medication timing, dosing, sleep medication, or diagnostic claims. These are widely used lifestyle strategies, not treatment, and not a substitute for evaluation by a qualified clinician. ## Methods Apply references/adhd-methods.md as ACTIONS on the dial, not advice you recite. Start with implementation intentions and externalized time. See references/workflows.md for extended multi-step scenarios, references/taxonomy.md for how areas and activity types map to the dial, references/calendars.md for connected-calendar sync, event kinds, and mirroring, references/reflection.md for reviewing how a past day actually went, and references/limits.md for what each plan allows and how to read a refusal. ## Feedback If a tool loops, needs a workaround, or the user hits a limitation in Reassign itself, report it with `mcp__reassign__send_feedback`.