Epics & Tickets
Epics group related work. Tickets are the atomic units that agents implement. Dependencies enforce execution order — the graph drives everything.
Epics
An epic is a logical grouping of tickets. Nothing more, nothing less.
Epics don’t have their own implementation — agents never “implement an epic.” They implement tickets. The epic exists to organize tickets into coherent chunks that humans can reason about and that the orchestrator can use to structure parallel execution.
What Defines an Epic
| Field | Purpose |
|---|---|
epicNumber | Auto-assigned sequential number |
title | Name of the epic |
objective | What this epic achieves as a whole |
status | todo → in_progress → completed (auto-calculated) |
order | Execution priority order |
acceptanceCriteria | Conditions for the epic to be considered complete |
Epic status is fully automatic. When the first ticket in an epic starts a work session, the epic moves to in_progress. When every ticket in the epic reaches done, the epic moves to completed. You never manually transition an epic.
How to Think About Epics
Group by functional area, not by technical layer. “Core Authentication” is a good epic — it contains everything related to login, registration, and session management. “Database Migrations” is a bad epic — it scatters related work across functional boundaries and forces artificial cross-epic dependencies.
A good decomposition produces epics that can run in parallel with minimal cross-epic dependencies. If every ticket in Epic 2 depends on a ticket in Epic 1, they probably should be one epic with internal ordering.
💡 In autonomous implementation, the orchestrator uses epics as the unit of team assignment. One team per epic (or per batch, depending on strategy). Epics that can run in parallel = more agents working simultaneously = faster completion.
Tickets
A ticket is the atomic unit of implementation. It describes a single, focused piece of work that an agent can complete in one work session without needing context from other active tickets.
Anatomy of a Ticket
Identity and classification:
| Field | Purpose |
|---|---|
ticketNumber | Auto-assigned sequential number |
title | Concise name describing the deliverable |
complexity | small · medium · large · xlarge |
priority | critical · high · medium · low |
Complexity and priority influence how the orchestrator assigns work. Critical tickets are picked first. Large tickets may get dedicated workers instead of being batched.
Implementation contract:
| Field | Purpose |
|---|---|
steps[] | Ordered implementation steps for the agent |
acceptanceCriteria[] | Conditions that must be met for the ticket to pass review |
dependencies[] | What must be done before this ticket can start |
Steps are the implementation instructions. Each step should describe a concrete action: “Create JwtService class in src/auth/jwt.service.ts” — not “implement token generation.” The more specific the steps, the less the agent guesses.
Acceptance criteria are the contract. They define what “done” means in verifiable terms: “Tokens are signed with RS256 algorithm” and “Invalid tokens return 401 with error body { error: 'INVALID_TOKEN' }.” The validator checks these during Implementation Review.
File expectations:
| Field | Purpose |
|---|---|
filesToCreate[] | New files this ticket produces |
filesToModify[] | Existing files this ticket changes |
File expectations serve two purposes. First, the Implementation Review checks whether expected files were actually delivered. Second, the dependency graph uses file information to prevent two tickets from modifying the same file simultaneously — avoiding merge conflicts in parallel execution.
What Makes a Good Ticket
Atomic. A ticket should produce a working, testable increment. “Set up User model and database schema” is atomic — you can run migrations and verify the table exists. “Build the entire auth system” is not — it’s an epic disguised as a ticket.
Self-contained context. When a work session starts, the agent receives the ticket’s steps, acceptance criteria, and dependency outputs. This should be enough. If implementing a ticket requires reading 5 other tickets to understand what’s going on, the ticket is too coupled.
Concrete steps. “Implement password hashing” is vague. “Create hashPassword function in src/auth/hash.ts using bcrypt with cost factor 12, export as named export, add unit test in tests/auth/hash.test.ts” is implementable.
Dependencies
Dependencies are the connective tissue of the specification. They define execution order — which tickets must complete before others can start. The dependency graph is a directed acyclic graph (DAG) where nodes are tickets and edges are dependency relationships.
Two Types of Dependencies
blocks — The dependent ticket cannot start until the dependency is completed.
This is the most common type. Ticket B depends on Ticket A because B needs something A creates to exist first.
Example: “Build registration endpoint” blocks on “Set up User model and database schema.” The endpoint can’t be built until the User model exists — the code literally won’t compile without the table and type definitions.
requires — The dependent ticket needs the result of the dependency.
This is subtler. The dependent ticket doesn’t just need the dependency to be done — it needs to consume its output.
Example: “Write E2E tests for auth flow” requires “Build login endpoint” AND “Build registration endpoint.” The tests don’t just need these endpoints to exist — they need to call them, verify their behavior, and assert on their responses. The test ticket consumes the output of both dependencies as its input.
When to Use Which
In practice, most dependencies are blocks. Use requires when the dependent ticket explicitly consumes the output of the dependency — test tickets that exercise implemented endpoints, integration tickets that wire together separately-built components, documentation tickets that describe implemented features.
The distinction matters for the Implementation Review. requires dependencies are scrutinized more carefully — the reviewer checks not just that the dependency is done, but that its output was actually used by the dependent ticket.
⚠️ SpecForge prevents circular dependencies automatically. If you try to add a dependency that would create a cycle, the operation is rejected with a description of the cycle path.
The Graph
When all tickets and dependencies are defined, the specification forms a directed acyclic graph. This graph is the execution plan.
Waves
The graph naturally produces waves of parallelizable work:
| Wave | What it contains |
|---|---|
| Wave 1 | Tickets with no dependencies — immediately ready |
| Wave 2 | Tickets that depend only on Wave 1 — unlock when Wave 1 completes |
| Wave 3 | Tickets that depend on Wave 1 or Wave 2 — and so on |
Each wave is a batch of tickets that can execute in parallel with zero risk of collision. The dependency graph guarantees it — no ticket in Wave 2 touches anything that another Wave 2 ticket is working on, because they all depend on different Wave 1 outputs.
Critical Path
The critical path is the longest chain of sequential dependencies in the graph. It determines the minimum time to complete the specification, regardless of how many agents you throw at it.
get_critical_path computes this chain and returns the total estimated effort. If your critical path is 8 tickets long but you have 50 tickets total, that means 42 tickets can be parallelized around the critical path. That’s where agent scaling pays off.
Why the Graph Matters
Without the graph, parallel agents collide. Agent A modifies a file that Agent B is about to read. Agent C implements a feature that depends on something Agent D hasn’t finished yet. Agent E makes an architectural decision that contradicts Agent F’s approach.
The graph eliminates all of this. It’s not a suggestion — it’s an enforcement mechanism. An agent literally cannot start a ticket until every dependency is done and validated. The graph is the traffic controller that makes parallel safe.
See Also
- Specifications — The parent that contains epics
- Quality Gates — Validate before and after implementation
- Work Sessions — How agents execute tickets
- Ticket States — Full state machine with auto-calculation rules
- Lifecycles — The three cycles that drive SpecForge