Cycles that forecast - capacity you can check, and the views you read the plan through
Rezee cycles now have issue sizes, a capacity target, a forecast built from the cycles you already finished, and a record of every scope change. Saved views and project labels are how you read the plan.
Sep 29, 2026 · 17 min read · Kash Gohil · LinkedIn · X
Every cycle starts with a guess. Somebody puts seventeen issues into Cycle 12, and the team agrees it looks about right. Two weeks later five of them carry over. Nobody can say if the plan was too big, if the work grew, or if the estimates were wrong. So the next plan is the same guess again.
Planning tools tend to answer this in one of two ways. Some do not guess at all. Others show a velocity number, and you cannot check where it came from. We wanted a third way: a forecast that names every input, and that measures itself against the cycles it forecast.
That work landed in mid-September. This post explains exactly how the forecast is calculated. Then it covers the two ways you read a plan once it exists: saved views, and labels on issues and projects.
Size is coarse on purpose
A forecast needs a unit. Issues now have an optional size: S, M, L or XL. Each size has a fixed weight in size units:
| Size | Units |
|---|---|
| S | 1 |
| M | 2 |
| L | 4 |
| XL | 8 |
The weights double. A larger coarse estimate is also a less certain one, and doubling says that. You cannot change the weights, and size is not story points. There is no 3, no 5 and no 13, so there is nothing to argue about in planning.
An issue with no size counts as M. We did not want the forecast to stop working on the first day, when nothing has a size yet. But a guess must not hide. Every load says how many issues it counted that way, for example "2 unsized, counted as M".
Only a person sets a size. If an agent tries, the API answers 403 with "an agent may suggest a size, not set one". kobeni can tell you that it thinks REZ-42 is an L. It cannot commit the team to that.
Size is on the issue page beside Priority. It is also on cards, in the board filters, in saved views and in the workspace export. The phone shows it on the issue screen, read-only.
Planned load and the capacity target
A cycle's planned load is the sum of the size units of every issue in it, except cancelled and archived issues. Completed units are the part of that load that is Done.
A capacity target is the number of units a cycle plans for. A project sets a default in its cycle policy. One cycle can override it, for example for a week with a holiday in it. The cycle's own target wins, then the project's. With neither, there is no target.
When the load goes past the target, the cycle page says so:
48 units planned against a target of 40.
That is a warning and nothing more. Rezee never refuses an issue that you add to a cycle, and it never asks you to confirm. A planning tool that argues with you gets worked around, and then its numbers mean nothing.
This comparison needs no history, so it works on the first day. It also runs on your device, from the local store. The server and your device call the same function, so the cycle page and the API cannot disagree about a load.
How the forecast is calculated
The method is called throughput-v1. It is deterministic, and it has three inputs:
- Planned load, as above.
- Throughput: the completed units of each of the six newest settled cycles in the same sequence. For a project's cycle, that is the project's earlier cycles. A cycle settles when it ends, as the next section explains.
- The capacity target, when there is one.
From the throughput sample it takes three numbers:
- the median, which the cycle page shows as Expected
- the 20th percentile, which is the low end of the range
- the 80th percentile, which is the high end
Percentiles use linear interpolation between the two closest ranks. With six values that changes the answer, so here is a full example.
Say the Runner sandbox project has six settled cycles. They completed 36, 31, 44, 38, 34 and 40 units. Sorted, that is 31, 34, 36, 38, 40, 44. Six values have ranks 0 to 5.
- The median is at rank 0.5 × 5 = 2.5. That is halfway between 36 and 38, so Expected is 37.
- The low end is at rank 0.2 × 5 = 1, which is 34.
- The high end is at rank 0.8 × 5 = 4, which is 40.
Cycle 12 holds 17 issues: two S, seven M, five L, one XL and two with no size. That is 2 + 14 + 20 + 8 + 4 = 48 units. The cycle page shows:
- Planned: 48 of 40 units, with "2 unsized, counted as M" under it
- Expected: 37 units, with "34 to 40 over the last 6 cycles" under it
It also shows two warnings:
48 units planned against a target of 40.
48 units planned; recent cycles finished at most 40.
The second one is the over-throughput warning. It appears when the planned load is above the high end of the range. The target is a number somebody chose. The high end is a number the team produced. When both warnings appear, the plan is larger than the team's own record says it can finish.
We use a median and a range, not an average. One cycle with a holiday in it pulls an average down for six cycles. It moves the median much less. The range shows how much your cycles vary, which a single number hides. A team with a range of 34 to 40 and a team with a range of 12 to 40 have the same high end. They should not make the same plan.
Three closed cycles before it gives advice
A forecast from one cycle is a guess with a number on it. So the forecast shows as advice only when the project has at least three settled cycles. Until then, Expected shows a dash and the line under it says "Collecting evidence: 1 of 3 closed cycles". The capacity target comparison still works, because it is not a forecast.
Between three and six cycles, the sample is every settled cycle there is. After six, the oldest one drops out each time a new cycle settles. A team that changed its size or its work is forecast from its recent self, not from last year.
A cycle closes once
The forecast reads settled cycles, so settlement has to be exact. Once an hour, Rezee looks for cycles whose end date has passed. Each one settles once, in one transaction:
- It locks the cycle, and skips it if it already settled. Two servers that run the same tick settle it once.
- It writes the outcome: what was in the cycle at its start, what was added and removed during it, what completed and what carried over. It records the same numbers for each assignee.
- It applies the project's rollover policy to the unfinished work.
- It writes one activity line for each issue that moved.
After that, the cycle's dates are fixed. A request to change them gets "this cycle has closed, so its dates are fixed". You can still add or remove issues by hand. Rezee records that as a scope change after the end, and it never starts a second rollover.
The cycle policy
A project's cycle policy says what happens around its cycles. You edit it in the project's rail, and the rail reads it back as a sentence. It has four parts.
Unfinished work when a cycle closes. There are three choices. "Stays in the cycle that ended" is the default. The others are "Moves to the next cycle" and "Leaves the cycle". The next cycle is the project's earliest cycle that starts at or after the end of the closed one. If there is none, nothing moves, and the outcome records that.
Joins the current cycle. There are two switches, "When work starts" and "When work is done". They only fill a blank. An issue with no cycle that enters Active or Review, or Done, joins the project's current cycle. The editor says it plainly: "A cycle somebody picked is never changed." A request that clears the cycle on purpose is a choice too, and auto-add leaves it alone. Imports never auto-add, so last year's work does not land in this week's cycle.
The "When work is done" switch is there for the forecast. Work that somebody finished without planning it still counts in the cycle where it finished. Without it, throughput undercounts every team that fixes things as they go.
Capacity target, as above.
Cooldown. This is a gap of days that the cadence leaves after each cycle. With a cooldown, cycle k starts at the anchor date plus k × (length + cooldown). A change moves only the windows that have not opened yet. During a cooldown there is no current cycle, so auto-add does nothing.
A project with no policy behaves exactly as it did before. Nothing moved on the day this shipped.
When the policy moves an issue, the issue's activity says so. The line names the policy, not a person, because no person did it:
carried this into Cycle 13 by the project's rollover policy
added this to Cycle 12 by the project's auto-add policy
Owners, admins and the project's planning teams can change the policy. Agents cannot. The refusal reads "an agent may suggest cycle settings, not change them".
Scope history that the database writes
"We added three things in the middle of the cycle" is a claim people make at retros. Now you can check it. Each time an issue enters or leaves a cycle, the database writes a row. The row holds the issue, added or removed, its size and status at that moment, the time, the cause and the person.
This is a trigger on the issues table, not application code. Issues enter and leave cycles through many writers: an edit, issue creation, a project move, a new parent issue, the rollover policy, and the deletion of a cycle. A rule that each writer must remember is a rule that one writer will forget. Rows in this table cannot be changed after they are written.
The cycle page lists the changes with the cause in words, such as "by hand", "filed into it", "project changed", "rollover policy" or "imported". Each change also says when it happened against the cycle: "before it started", "during" or "after it ended".
The forecast is graded
When a cycle becomes current, Rezee records a forecast snapshot. The snapshot holds the planned load, the cycles in the sample, the median and range, and both warnings. Rezee records it for every cycle, also before the forecast shows as advice. That way the evidence exists by the time anyone reads the forecast. When the cycle settles, the outcome row says what actually happened.
Calibration compares the two for each settled cycle: the predicted median and range, the units actually completed, whether the actual number fell in the range, and the error. For a project it reports:
- how many past forecasts landed in their range, which the cycle page shows as, for example, "4 of 6 past forecasts landed in range"
- the median absolute percentage error
- how often an over-throughput warning came before work carried over
The last number is the one we watch most. A warning that never predicts anything is noise, and this number shows whether it is. Each snapshot also records its method name. When a better method comes, it is graded on its own snapshots, and it never rewrites the old ones.
Four signals beside the forecast
The cycle page shows four more figures from the same settled cycles. None of them is an input to the forecast.
- Cycle time: the median number of days from start to done, with "8 in 10 within" the 80th percentile. An issue's start is the first time it entered Active or Review.
- Running long: open issues in this cycle that started longer ago than that 80th percentile. Each one shows when it started.
- Carried over: the share of units that carried over, out of the work still counted when recent cycles closed.
- People: each assignee's planned units now, against what they usually finish, for example "usually finishes 9". Agents are on this list too. You can see when kobeni holds more work than it has ever finished in a cycle.
Pull request size, repository breadth, design readiness and dependency counts are not inputs. They can join a later method version when there is outcome evidence to judge them against. Until then, adding them would make the forecast look smarter without making it more correct.
The forecast, the scope history and the calibration are also on the REST API and the MCP tools cycle_forecast, cycle_scope and cycle_calibration. Each answer includes its inputs, so an agent that reads a forecast can also tell you why it says what it says.
Reading the plan through saved views
A forecast tells you whether the cycle fits. Most days the question is smaller. What is mine? What waits on a review? What shipped but is still open? Plan has a Views tab for these questions.
A view saves a query and a layout. The query has a subject, issues or docs, and a set of clauses. Clauses combine with AND, and the values inside one clause combine with OR. Issue clauses cover phase, stage, priority, size, assignee, author, team, project, cycle, labels, repository, archive state, text, custom fields and facts. The layout is a list or a board, with grouping, order and the fields to show.
Some values resolve against the person who reads the view. me is the reader. mine is the reader's teams. current is the current cycle of each issue's project. So one shared view, "my open work in the current cycle", answers a different question for each member, and each answer is correct.
Views store phases, not stage names. If a team renames its "In Review" stage, nobody's views break, because the phase of a stage never changes.
Facts, with the row that made them true
Some questions are not about a field. "Which issues have a pull request that waits on a reviewer?" needs the pulls. A view can filter on facts:
awaiting_review: a linked pull is open, is not a draft, and has a review request with no answerdeployed_not_done: a closing merge reached the last environment, and the issue is not Done or Cancelleddesign_not_approved: the issue links to a design that is still in Draft or In reviewagent_waiting: an agent task for the issue waits for an approval or an answer
Each match carries the row that made the fact true, and the view links to it: the pull, the deployment, the canvas or the task. A fact reads only what the reader can see. A pull in a repository you cannot open is not evidence for you. So two people can get different results from one shared view. That is correct, and it is the reason a shared view stores the query and never the results.
Five views come built in: "My work", "Waiting for review", "Deployed, not done", "Design not approved" and "Agents waiting on a person". You cannot edit a built-in view. You can copy one and change the copy.
Who sees a view
A view is personal, team or workspace. A personal view reaches only its owner. A team view reaches the members of that team, and when somebody leaves the team, the next sync removes it from their devices. A workspace view reaches every member. Members can share views with teams they are on. Owners and admins manage workspace views. Agents can read and run views over REST and MCP, but they cannot create, edit or share one.
The same evaluator runs on your device and on the server. Your device runs it over the local store. The server runs it over the rows that the same reader would get. A test suite checks that both return the same matches, in the same order, with the same evidence.
On the phone, Plan's header opens your views as lists. Editing stays on the web. The workspace export includes workspace and team views as perspectives.json. It leaves out personal views, because they belong to one person.
Labels that a view can trust
A view that filters on a label is only as stable as the label. So labels got the rules that a saved view needs.
- Scope. A label belongs to the workspace or to one team. Only the team's members see a team label, its name or its color.
- Groups. A group holds labels, and it is one-of-many. An issue has at most one label from a group. Applying a label removes its sibling in the same write, and the database enforces this.
- Archive. An archived label leaves the pickers. It stays on the issues that have it, and views that filter on it still match.
- Merge. When you merge one label into another, every issue moves across and the old id forwards to the new one. A view that names the old label keeps working.
- Usage first. Before you archive or merge a label, the Labels page shows what uses it: issues, Intake rules, views and playbook runs. Your change carries a token of what you saw. If something started to use the label in the meantime, Rezee refuses the change and shows the new usage.
Delete is still there for mistakes. Rezee refuses it while anything uses the label. Agents can apply labels, but they cannot manage them.
Project labels, and the projects list as a plan
Projects now have labels of their own. They are in the same table as issue labels, with a subject column that is issue or project. The other option was a second table. That would have copied the label service, the sync model, the Labels page and the forwarding rule. Every later label change would have had to land twice.
One table has a cost too: every reader must ask for its set. So the shared helpers mean issue labels unless a caller asks for project labels, and the database refuses a project label on an issue. The Labels page has an Issue labels tab and a Project labels tab.
Project labels are always workspace labels. A project can belong to several teams, so a team label on a project would have no single team to follow. Groups work as they do for issues. Add Stage/Build to a project and Stage/Explore comes off.
The projects list can now group by:
- status
- team
- target month or quarter
- health, from the project's latest published check-in
- a label, or the labels of one group
It also filters by label, and the grouping and the filter stay in the URL. A project with two teams or two labels appears in both bands. The band for "none" ("No team", "No target date", "No check-in", "No label") is always last. Group by quarter and filter by a label, and you have a roadmap that you can send as a link.
The grouping is one function in a shared package, so the phone puts projects in the same bands as the web. On the phone you can also label a project from its screen.
A label on a project is a fact about that project. Nobody learns it about a project they cannot reach. Projects have no activity feed, so Rezee writes each label change to the workspace audit log.
When the plan needs you
Planning also reaches you as notifications: an assignment, a review request, a project check-in that is due. Delivery got per-person controls in the same weeks.
Each kind of notification has three channels: Inbox, push and email. You choose them per kind. Email goes only to a verified address, and only for a line that is still unread after 10 minutes. For an agent that waits on you, the delay is 2 minutes. One email per workspace collects every line that is due, and each email has a one-click unsubscribe.
Quiet hours apply per channel. The Inbox still gets the line. Push stays silent. Email waits until the quiet window ends, and goes only if the line is still unread. An agent that waits on your approval or your answer always reaches your Inbox, and quiet hours never hold it back.
What it does not do
- The size weights are fixed. A setting would let each team tune the forecast until it agrees with them. Then calibration would grade the tuning, not the method.
- There is one forecast method. It does not simulate, and it does not read pull requests or dependencies.
- Cycles with no project have no policy. The workspace-wide cycle sequence keeps unfinished work where it is and adds nothing automatically.
- Views cover issues and docs only. There are no views over pull requests, runs or chat, and you cannot subscribe to a view yet.
- The phone reads, the web edits. On the phone, sizes and views are read-only.
FAQ
Do I have to size every issue?
No. An unsized issue counts as M, and the cycle page says how many issues it counted that way. If most of a cycle is unsized, the forecast is mostly a count of issues. The page makes that visible, so you can decide if it matters.
Can an agent plan a cycle?
An agent can read the forecast, the scope history and the calibration, and it can suggest sizes and settings. It cannot set a size, a capacity target or a cycle policy. Those are commitments, and a person makes them.
How is this different from velocity?
Velocity is usually one average that you cannot open. This forecast shows its sample, uses the median and a range, waits for three closed cycles, and grades every forecast against what happened. For the wider view of how Plan fits with the rest of the workspace, see Plan & Track.