> ## Documentation Index
> Fetch the complete documentation index at: https://lib.findy.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# Task Breakdown

> Breaking work into small, independent units: benefits, good-task conditions, split-or-merge criteria, breakdown steps, dependencies, and issue creation.

## Overview

Task breakdown is the practice of splitting a feature into small units of work
before implementation. Each task aims to merge on its own, revert on its own,
and drag no unrelated changes with it. The preparation done before writing
code determines [pull request granularity](/development/pull-request#granularity):
building PRs from the broken-down tasks lets you keep creating PRs at the
right granularity.

## Benefits

Listing and splitting tasks before starting looks like a detour, but across
the development cycle it turns out to be the fastest path.

<CardGroup cols={2}>
  <Card title="More accurate estimates" icon="calculator">
    Small, concrete tasks are easier to size than one large feature, so the
    total estimate carries fewer surprises.
  </Card>

  <Card title="Early agreement on the approach" icon="comments">
    Writing the task list in an issue and having it reviewed before
    implementation surfaces missing cases and wrong assumptions while they are
    still cheap to fix, which cuts rework.
  </Card>

  <Card title="PR granularity stays right" icon="code-pull-request">
    Building PRs from the broken-down tasks keeps each PR focused on one thing
    and prevents it from bloating.
  </Card>

  <Card title="Visible progress, easy hand-off" icon="list-check">
    A checklist of tasks makes status legible at a glance and makes handing
    work between people — or between people and AI agents — straightforward.
  </Card>
</CardGroup>

Good task breakdown also translates into providing AI agents with the right
context. Context engineering is the practice of preparing the context an AI
agent works with — instructions, reference material, and scope — so that it
contains exactly what the goal requires, no more and no less. A task with
uniform change content lets you load only the information that piece of work
needs, so the agent concentrates its limited context on one thing.

Task breakdown, [pull request granularity](/development/pull-request#granularity), and
context engineering are tightly linked: breakdown decides the unit of work,
that unit drives the granularity of the PR, and that granularity determines
the quality of the context the agent receives. Even when implementation is
delegated to AI agents, the starting point is a good breakdown.

## What makes a good task

A well-sized task satisfies four conditions at once.

<CardGroup cols={2}>
  <Card title="Merges without breaking anything" icon="code-merge">
    The change is safe to integrate on its own, and the application keeps
    working after the merge.
  </Card>

  <Card title="Includes its tests" icon="vial">
    Implementation and the tests that prove it ship in the same task, never
    separately.
  </Card>

  <Card title="Reverts in isolation" icon="rotate-left">
    Rolling it back does not disturb other tasks.
  </Card>

  <Card title="Reviewable in one sitting" icon="clock">
    It stays small enough that a reviewer can read it through without
    breaks and understand the whole change.
  </Card>
</CardGroup>

## Keep together or split apart

Cohesion decides the boundary. To judge whether two pieces of work belong to
the same task, apply three checks in order. If any answer forces them together,
keep them together.

<Steps>
  <Step title="Check independence">
    Does task B work correctly without task A? If not, they are one task.
  </Step>

  <Step title="Check completeness">
    Is task A a meaningful, mergeable unit on its own? If not, merge it into
    the task that gives it meaning.
  </Step>

  <Step title="Check revert impact">
    Does reverting task A also break task B? If so, they are one task.
  </Step>
</Steps>

Some combinations do not need the checks — they always land the same way.

<CardGroup cols={2}>
  <Card title="Always keep together" icon="link">
    * Implementation and its tests
    * An API endpoint and its routing
    * A data model and its migration
  </Card>

  <Card title="Always split apart" icon="scissors">
    * Refactoring from new features
    * A library upgrade from feature work
    * A performance change from feature work
    * A data migration from feature work
    * Each stage of a feature flag (add → enable → remove)
    * Features that do not depend on each other
  </Card>
</CardGroup>

## Breakdown steps

Breakdown is iterative. The first list does not need to be perfect; it gets
more precise as more people look at it and as the breakdown progresses.

This section walks through building a task list, using the task "Add a REST
API that returns a list of users" as an example.

<Steps>
  <Step title="Draft a task list from the requirement">
    Start by writing the rough requirement as an issue task list. A single
    top-level line is enough at this point.

    ```markdown theme={null}
    - [ ] Add a REST API that returns a list of users
    ```
  </Step>

  <Step title="Expand into independently shippable slices">
    Break the single line into pieces that ship on their own. Fetching the
    list, filtering, pagination, and sorting each became their own task.
    Build the feature by stacking small additions instead of implementing
    everything at once.

    ```markdown highlight={2-8} theme={null}
    - [ ] Add a REST API that returns a list of users
      - [ ] Fetch the list of users from the database and return it
      - [ ] Support filtering
        - [ ] id
        - [ ] name
      - [ ] Support pagination
      - [ ] Support sorting
        - [ ] id asc/desc
    ```
  </Step>

  <Step title="Review the list across roles">
    Have frontend, backend, and product reviewers look at the list before any
    code is written. Discussion turns vague items concrete: in this example,
    aligning in review pinned the name filter down to a partial match.

    ```markdown highlight={5} theme={null}
    - [ ] Add a REST API that returns a list of users
      - [ ] Fetch the list of users from the database and return it
      - [ ] Support filtering
        - [ ] id
        - [ ] partial match on name
      - [ ] Support pagination
      - [ ] Support sorting
        - [ ] id asc/desc
    ```
  </Step>

  <Step title="Keep splitting during implementation">
    When implementation reveals reality, feed it back into the list and split
    further. In this example, writing tests surfaced the hidden requirement of
    handling deactivated users, and the fetch task split into "return all
    users" and "exclude deactivated users". Keep updating and splitting the
    list during implementation instead of letting one task swell.

    ```markdown highlight={3-4} theme={null}
    - [ ] Add a REST API that returns a list of users
      - [ ] Fetch the list of users from the database and return it
        - [ ] Return all users
        - [ ] Exclude deactivated users from the list
      - [ ] Support filtering
        - [ ] id
        - [ ] partial match on name
      - [ ] Support pagination
      - [ ] Support sorting
        - [ ] id asc/desc
    ```
  </Step>
</Steps>

## Dependencies and parallelism

Once the list settles, map the dependencies between tasks and identify which
tasks can run in parallel. Tasks with no dependency on each other can be
implemented simultaneously — by different people, or by multiple AI agents.

For example, a bulk user registration feature breaks into five tasks: the
domain model comes first, the parser and the validator depend only on it and
run in parallel, the service layer combines them, and the API endpoint sits on
top.

```markdown theme={null}
- [ ] Add bulk user registration
  - [ ] Task 1: Define the domain model
  - [ ] Task 2: Implement the parser
  - [ ] Task 3: Implement the validator
  - [ ] Task 4: Implement the service layer
  - [ ] Task 5: Add the API endpoint
```

Mapping the dependencies of this task list produces the following diagram.

```mermaid theme={null}
flowchart LR
  T1[Task 1<br/>Domain model] --> T2[Task 2<br/>Parser]
  T1 --> T3[Task 3<br/>Validator]
  T2 --> T4[Task 4<br/>Service layer]
  T3 --> T4
  T4 --> T5[Task 5<br/>API endpoint]
```

## Turning tasks into issues

Once the breakdown and its dependencies are settled, create an issue per task.
Checkboxes in a task list cannot track assignees, discussion, or progress per
task. Promoting a task you are about to start into its own issue makes one
issue one unit of work, with the requirements and discussion for that task
collected in one place.

Structure the feature and its tasks as parent and child issues.

* **Parent issue** — represents the whole feature. It keeps the background,
  the goal, and the full task list, and links to each child issue so progress
  can be followed from one place.
* **Child issue** — represents one broken-down task. It states the task's
  requirements and completion criteria, and records the dependencies mapped
  earlier. If the tool supports linking parent and child issues, the
  children's progress rolls up to the parent.

On GitHub, this structure maps to two features: sub-issues and issue
dependencies. Sub-issues carry the parent–child relationship — which feature a
task belongs to — while dependencies carry the starting order — which task to
start after.

**Sub-issues (parent–child)** — adding the child issues to the parent as
sub-issues makes the feature-task hierarchy explicit, and the children's
completion rolls up to the parent as progress. See
[Adding sub-issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues)
in the GitHub Docs for the steps. For the bulk registration feature, the five
child issues hang under the parent issue.

<Card title="Parent issue: Add bulk user registration" icon="folder-tree">
  Sub-issues (0 / 5)

  * [ ] Task 1: Define the domain model
  * [ ] Task 2: Implement the parser
  * [ ] Task 3: Implement the validator
  * [ ] Task 4: Implement the service layer
  * [ ] Task 5: Add the API endpoint
</Card>

**Dependencies (starting order)** — record the starting order between child
issues as issue dependencies. Setting a dependency on Task 1 for the Task 2
issue makes it visible, even in lists, that Task 2 cannot start until Task 1
completes, and it can replace writing dependencies in the issue body. See
[Creating issue dependencies](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-issue-dependencies)
in the GitHub Docs for the steps. The dependencies of the bulk registration
feature form the following graph, where each arrow points to the issue it
depends on — the one that must complete first.

```mermaid theme={null}
flowchart RL
  T2[Task 2<br/>Parser] -->|depends on| T1[Task 1<br/>Domain model]
  T3[Task 3<br/>Validator] -->|depends on| T1
  T4[Task 4<br/>Service layer] -->|depends on| T2
  T4 -->|depends on| T3
  T5[Task 5<br/>API endpoint] -->|depends on| T4
```

Start with Task 1, which has no dependencies; Task 2 and Task 3 share the same
dependency and can proceed in parallel.

An issue created this way is a unit of work you can hand to a person or an AI
agent as is. With the requirements, completion criteria, and dependencies in
one place, the quality of the context the implementer receives is largely
decided at this point. Issues with no dependencies can be started in parallel.
