Working with epics
An epic is an issue that contains other issues. Everything else about it is an ordinary issue — it has a status, an assignee and a thread.
Epics have their own page at Epics in the sidebar, listed by progress rather than by status, with a count of how many people outside the company are subscribed to each. The issue board can also be filtered to Type: Epic.
Creating one
New epic, on the Epics page. It takes a title, and optionally a project, a priority, an assignee and a due date. The epic arrives empty and in the first column; what it is for is written on its own page, where there is an editor for it.
The form is shorter than the board's on purpose, because an epic has fewer fields that mean anything:
- No estimate. An epic has none of its own — the issues inside it are what get estimated, and the model refuses one.
- No parent epic. An epic cannot be filed inside another.
- A due date, though. The Epics page is ordered by it, and an epic without one sorts to the bottom.
Only projects that have the epic type enabled are offered. A project that has switched it off would refuse the epic, and offering it would be offering a choice that fails on submit.
The other way in is still there: set an existing issue's Type to epic on the board. Its
properties panel then loses the Epic row, since an epic cannot be filed inside another, and
gains an Issues in this epic panel with a progress bar.
Handing a new epic to an agent queues a run immediately, exactly as it does on the board.
Adding work
Three ways in, because planning happens in both directions — and sometimes while the issue is still being written.
From the epic — Add issue opens a dialog with two tabs:
- New issue — creates one directly inside the epic. It inherits the epic's project, because an epic spanning two projects is a planning mistake rather than a feature. Assign it to an agent here and a run is queued immediately.
- Existing issue — a searchable list of issues that can join. Only same-workspace, non-epic, not-already-in-an-epic issues appear.
From the issue — the Epic row in its properties panel.
While writing it — New issue carries an Epic field beside Project, so an issue can
be filed as it is opened rather than opened and then moved. The field is absent when there is
nothing to choose: a workspace with no epics, or a type of epic, which cannot be nested. Choosing
that type gives up a parent already selected rather than leaving a pair the form would refuse.
Filing at creation records no separate history entry. The epic is part of what was created, and a second line would only push the creation itself up the thread — the same reason the project an issue was opened in does not get one.
A finished epic is not offered. Whatever the workspace calls done or cancelled, an epic in either category is work somebody has declared over: filing new work under it either reopens a closed question or hides the work inside something nobody is looking at. It is asked of the category rather than the name, like everything else that reasons about status, so a workspace that calls it Shipped gets the same answer.
The exception is the epic an issue is already in, however it is classified. Dropping that one would leave the picker empty while the issue plainly sits inside something.
Tip: This also keeps the list usable. Epics accumulate, and a picker that offers every epic a workspace has ever had is one you scroll rather than read.
Removing work
The × on a row takes an issue out of the epic. The issue itself is untouched: it keeps its
status, comments, runs and history, and simply stops being grouped.
Deleting an epic does the same thing to all of its children at once.
The rules
Three, each enforced on every path and covered by tests:
- Only an epic can be a parent. Filing an issue under an ordinary issue is refused.
- An epic cannot be nested in another epic. One level, always.
- Nothing can be its own parent, and nothing can cross workspaces.
Two more protect data:
- An epic with children cannot be demoted. Change its type and you get "This epic still contains issues. Move them out first." — otherwise the children would point at something that is no longer a container.
- Promoting an issue to epic removes it from its own epic automatically, rather than creating an illegal nesting.
- An epic with children cannot be removed either. The same containment rule as demotion, for the same reason — and if the children are what should go, they go one at a time, each by somebody who can say it was created in error.
On the board
An issue's card names its epic, as a badge that links to it. A card said which project it was in and not which piece of work it was part of, which is the more useful of the two once an epic has more than a handful of children.
Tip: Filtering the board by type is the quick way to see an epic's work without the epic's own card in the way — the badge is on the children, and an epic is an issue with a card of its own.
Progress
Closed children over total children, where closed means a status your workspace has classified as
completed or canceled — not a status literally called done. Rename or re-classify a status
at Administration → Statuses and this figure follows, along with every other count in Félagi.
The same measurement as project progress, at a smaller scale.
Because epics cannot nest, there are no deeper levels to count and the number is always exact. If
Epic → Story → Task is ever wanted, both the rules and the counting have to change — worth
knowing before anyone asks for it.
Dates, and no estimate
An epic carries a start date and a due date. Together they are the bar on the Timeline and the window the Gantt measures capacity against: does the work left inside the epic fit in the working days left before the deadline.
On the Timeline itself the colour beside the bar is set by hand, not worked out from those dates — an epic underestimated in January turns red in March, which reads as slipping and means something else entirely.
There is no estimate field on an epic. The issues inside it are estimated, and a second
figure on the epic would be two answers to how long the same work takes. When this changed,
every epic that carried one had it converted into a start date — due date − estimate, which
is exactly what the Gantt had been inferring from it — so the planning input became a date
somebody can read and correct instead of a number nobody could see.
Milestones
A name, a date and a status, set on the epic itself. That is the whole object.
Everything a milestone could also have — an owner, an estimate, a conversation — is a reason to have filed an issue instead, and the epic already holds those. This exists so a plan can be stated without inventing a piece of work to stand for it.
| Status | What it means |
|---|---|
| Planned | Written down, and expected on its date |
| At risk | Somebody has said it will not be met, before the date arrives |
| Reached | It happened, and the day it happened is recorded with it |
Missed is not one of them. It is worked out from the date and the absence of the other two, so a stored answer would still read "missed" after somebody moved the date — which is exactly the moment a plan most needs to be read correctly.
At risk is the only value arithmetic cannot produce, and the reason the status column is worth having at all. Anything else on this list can be inferred from a date.
The day it happened
Marking a milestone reached records today, not its target date. The gap between the two
is shown beside it as +10d, and it is the only honest measure of how a plan went.
Correcting the date afterwards keeps the day it happened. Moving a target is how a plan gets corrected after the fact, and overwriting the other date would erase the only figure worth having.
What they appear on
Each milestone is a named diamond on the epic's bar on the Timeline, which is the page somebody outside the team is most likely to be shown. An epic with no milestones has its dated issues drawn there instead, fainter, until it has some.
They are also listed in the Timeline's own panel — the only place a Management reader can see them, since the epic's page is behind the working gate.
What they do not do
- No notifications. Nothing is sent when one is reached or missed. Subscribers hear about the epic, not its checkpoints — see Keeping clients told
- No API. They cannot be read or written over
/api/v1yet - Nothing depends on one. A milestone does not block work, hold a status, or gate a release. It is a statement about a date
Removing an epic from the board keeps its milestones: they come back if it is restored.
Seeing them all at once
Two pages, and they answer different questions:
- Epics is the list — every epic, progress, due date, who is following it
- Timeline is the same epics against the calendar, coloured by whether each one will land on its date, with the unscheduled ones listed underneath
The Timeline is also what somebody in the Management role has instead of a board, which makes an epic's dates worth setting: an epic with none appears there under Not scheduled, by name.