|
| 1 | +--- |
| 2 | +name: prep-cycle |
| 3 | +description: Build or adjust a Linear cycle — for a whole team or just yourself. Size capacity from last-3-cycle velocity, fill with backlog bugs/high-priority items first and project work after (in your chosen project focus order), with no unassigned issues. Use when planning/prepping a cycle for a team, or when one member wants to fill/rebalance their own cycle work. |
| 4 | +--- |
| 5 | + |
| 6 | +# Prepare a Cycle |
| 7 | + |
| 8 | +Assemble a capacity-sized cycle by **curating existing issues** (from focus projects + the backlog) — not by authoring new ones. The output is a cycle where each in-scope member is loaded up to their historical velocity, high-priority/bug work sits ahead of project work, and nothing in scope is unassigned. |
| 9 | + |
| 10 | +If you do need to *create* a missing issue along the way, follow the [[create-issue]] standard for it. |
| 11 | + |
| 12 | +## Before you start — resolve scope, team & target |
| 13 | + |
| 14 | +1. **Scope** — determine who this run is for: |
| 15 | + * **Whole team** — prep/rebalance the cycle for every included member (the default when prepping a team's cycle). |
| 16 | + * **Just me / a single member** — a member filling or adjusting *their own* cycle work. Skip the roster-inclusion prompt entirely; the one member is the roster. Resolve "me" via `get_user` ("me"), or use the named member. |
| 17 | + If the request doesn't make scope obvious (e.g. "prep Alpha's cycle" → team; "fill my cycle" / "sort out my sprint" → self), ask which. |
| 18 | +2. **Team** — the skill is team-agnostic; **always ask which team** unless the user already named one. Resolve options from `get_user` ("me") / `list_teams`. In self mode, default to the team that owns the target cycle. |
| 19 | +3. **Target cycle** — ask whether you're filling the **current** cycle or the **next** one. Get cycle numbers via `list_cycles` (type `current` / `next`). Call the target cycle's number `C`. |
| 20 | +4. **Build vs adjust** — a target cycle may already hold issues. If so, ask whether to **top up** in-scope members to capacity (leave existing cycle items in place, only add) or **rebalance** (also reconsider what's there). Either way, only ever touch the in-scope members' own work — never move or reassign another member's issues. |
| 21 | + |
| 22 | +## Step 1 — Roster & focus (prompt per in-scope member) |
| 23 | + |
| 24 | +* **Inclusion** — *team mode only.* Get the team's members (`get_team` / `list_users team:<team>`) and ask which are in this cycle (`AskUserQuestion` multiSelect; if more than 4 members, split across questions, max 4 options each). If the team has a **default roster** below, pre-select those as the default and just confirm. In self mode, skip this — the single member is the roster. |
| 25 | + |
| 26 | + **Default rosters** (the usual cycle members for a team; confirm, don't assume): |
| 27 | + * **Alpha** — Phil, Palla, Alex, Facundo, Spyros. |
| 28 | + |
| 29 | + Add other teams' defaults here as they're established. |
| 30 | +* **Project focus order** — for each in-scope member, ask the **ordered** list of projects they focus on (first = highest focus). `AskUserQuestion` options don't encode order reliably, so either ask the projects as a multiSelect then confirm the resolved order back in text, or ask the user to state the order explicitly. List the team's projects (`list_projects team:<team>`) as the option set. In self mode this is just one quick question for the calling member. |
| 31 | + |
| 32 | +Record, per in-scope member: `{ projects: [ordered] }`. Out-of-scope members get nothing assigned and their existing work is left untouched. |
| 33 | + |
| 34 | +## Step 2 — Size capacity from the last 3 cycles |
| 35 | + |
| 36 | +For each in-scope member `m`, compute their **per-cycle velocity** from completed work: |
| 37 | + |
| 38 | +* For each of cycle numbers `C-1`, `C-2`, `C-3`: `list_issues` with `cycle:<number>`, `assignee:<m>`, and a completed state filter (`state:Done` / completed-type). Sum the `estimate` of those issues → that cycle's completed points for `m`. |
| 39 | +* `capacity(m) = round(mean of the available cycle totals)`. If `m` has fewer than 3 cycles of history, average over what exists. If `m` has **no** history, ask the user for a manual capacity rather than guessing. |
| 40 | + |
| 41 | +Report the per-member capacities (and team total in team mode) before filling, so the user can adjust. The cycle is filled **up to** each member's capacity — never over it. In self mode, subtract any work already in the target cycle for `m` from their capacity so a top-up doesn't overload them. |
| 42 | + |
| 43 | +> Only **completed** issues count (Linear "Done"/completed type). Canceled/Duplicate do not. Issues without an `estimate` contribute 0 to history and can't be allocated by points later — flag them (see Step 4). |
| 44 | +
|
| 45 | +## Step 3 — Backlog bugs & high-priority items go first |
| 46 | + |
| 47 | +Pull **non-project** backlog work that must jump the queue: |
| 48 | + |
| 49 | +* `list_issues` for the team with `state` of backlog/triage type and **no project**, filtered to: priority **Urgent (1)** or **High (2)**, OR carrying a bug label (`Bug`). Run the queries you need and dedupe. |
| 50 | +* **Team mode:** for each such issue ensure an assignee — keep the existing one; if **unassigned**, ask the user who to assign it to (these cannot stay unassigned), preferring the member whose focus/expertise fits. |
| 51 | +* **Self mode:** only pull items already assigned to `m`, plus unassigned ones the member explicitly chooses to take — don't hand out bugs to other people. Leave items assigned to others alone. |
| 52 | +* Add each in-scope item to the target cycle. These count against that member's `capacity(m)` and are placed **ahead** of their project work (see ordering note below). |
| 53 | + |
| 54 | +## Step 4 — Fill remaining capacity with project work (in focus order) |
| 55 | + |
| 56 | +For each included member `m`, after their Step-3 items, walk their `projects` in focus order and pull issues to fill the rest of `capacity(m)`: |
| 57 | + |
| 58 | +* `list_issues` per project, restricted to unstarted/backlog issues. Within a project, take them in priority order (Urgent → High → Medium → Low), then backlog order. |
| 59 | +* Assign each pulled issue to `m` (if it already has a different assignee, leave it for that person and skip — don't reassign someone else's in-progress work) and set its `cycle` to the target. |
| 60 | +* Keep a running total; stop adding to `m` once the next issue would exceed `capacity(m)`. Move to the next project in focus order only while capacity remains. |
| 61 | +* **Issues with no estimate** can't be point-allocated. Don't silently skip or guess: **propose an estimate** on the 1/2/3/5 scale (per [[create-issue]]) from the issue's scope/complexity, **prompt the user to confirm or correct it**, then write it back with `save_issue` (`estimate`) before counting it toward capacity. Batch these confirmations (one prompt covering several issues) rather than one prompt per issue. |
| 62 | + |
| 63 | +Don't assign the same issue to two members. If a project appears in multiple members' focus lists, split its issues between them as you go. |
| 64 | + |
| 65 | +## Step 5 — Enforce: no unassigned items |
| 66 | + |
| 67 | +Everything **this run added** to the cycle must have an assignee. In team mode, `list_issues cycle:<C> assignee:null` for the team must come back **empty** — assign anything unassigned (ask when the owner isn't obvious) or remove it. In self mode, only guarantee this for the items you added/own; don't touch pre-existing unassigned issues you didn't put there (mention them if you spot them). |
| 68 | + |
| 69 | +## Step 6 — Write & report |
| 70 | + |
| 71 | +* Apply changes with `save_issue` (`id`, `cycle:<C>`, `assignee`) per issue. |
| 72 | +* Report a per-member summary: capacity, points allocated, the ordered list of issues (bugs/high-priority first, then project work by focus order), and any flagged items (no estimate, newly assigned, capacity left unfilled because the projects ran dry). |
| 73 | + |
| 74 | +## Ordering note (Linear limitation) |
| 75 | + |
| 76 | +This MCP can't set a manual board position within a cycle, so "ahead of project work" is expressed through **priority** — Urgent/High bug items already sort above Medium project work. If a strict manual order is needed beyond what priority gives, call it out so the user can drag-order in the Linear UI. |
| 77 | + |
| 78 | +## Tools |
| 79 | + |
| 80 | +`get_user`, `get_team`, `list_users`, `list_projects`, `list_cycles`, `list_issues` (by `cycle` / `project` / `assignee` / `state` / `priority` / `label`), `save_issue` (set `cycle`, `assignee`, `estimate`). |
| 81 | + |
| 82 | +**Linear MCP reliability (learned the hard way — follow exactly):** |
| 83 | +- **Apply `save_issue` writes ONE AT A TIME, never in parallel.** Multiple `save_issue` calls issued together in one turn get silently dropped — only some persist. Sequential, one write per turn, is reliable. |
| 84 | +- **All reads lag (eventual consistency)** — `list_issues`, `save_issue` echoes, *and even `get_issue`* can return pre-write state for several seconds after a write. A "missing" change is usually read-lag, not a failed write. To confirm: re-issue the (idempotent) `save_issue` and check that its echo reflects the change (the echo returns the last *persisted* state), rather than trusting one `get_issue`. |
| 85 | +- `list_issues` for a whole cycle/large project can exceed the output limit and be saved to a file — filter (by `state`/`priority`/`assignee`) or `jq` the file instead of widening the limit. |
| 86 | +- Large multi-cycle history: query per cycle and aggregate completed `estimate` by assignee with `jq`. |
0 commit comments