task-decomposition

verified

932fa134-7742-433b-817e-e40b8fc8ce3e

Decompose a feature or bug into an ordered list of small, independently testable subtasks before writing any code. Use when a task feels too big to start or keeps sprawling.

Metadata

Skill ID
932fa134-7742-433b-817e-e40b8fc8ce3e
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
planningdecompositionsubtasksbreaking-down-workscope
Signature
verified
Integrity
OK
Content hash
6e74e3b5012f5d0dd71d6f46043e13ba93a6d09ba6e1e2a11e98e62b11c0cb51
Created
2026-08-15T05:27:30Z

Skill file

Raw skill file (markdown source)
# Task Decomposition

Use when a task is too big to start in one go, keeps sprawling as you work, or you
need a defensible plan of attack for an "epic" or "feature" request.

The core idea: before writing code, turn the request into a flat, ordered list of
**leaf tasks** β€” each one small enough to be *verified by a single command*. A task
you cannot verify with one command is not yet a leaf; split it again.

## 1. The leaf-task rule

A leaf task is done when **one command** proves it is done. That command is a test
run, a script run, a `git diff`, or a single SQL/`curl` check. If verifying the
task requires "and then also…", it is two or more leaves.

| Not a leaf (split again) | Leaf (one verify command) |
|---|---|
| "Implement user auth" | "Add `User` model + migration; verify `python manage.py makemigrations --check`" |
| "Add login endpoint" | "Add `POST /login` returning a JWT; verify `pytest tests/test_login.py`" |
| "Set up the database" | "Add `users` table DDL; verify `psql -f schema.sql -c '\\d users'`" |

Test the rule: for every leaf, write the exact verify command next to it. If you
cannot write one, the leaf is too coarse.

## 2. Ordering heuristics

Order the leaves as a **DAG, not a list**. Draw arrows for "B depends on A". Then
schedule with:

1. **Highest risk / highest uncertainty first.** Unknowns discovered early are cheap;
   unknowns discovered at the end force rework.
2. **Dependencies before dependents.** A leaf is only scheduled after its parents.
3. **Foundations before polish.** Schema, interfaces, and contracts before UI and docs.

```
User auth decomposition (DAG order):
  1. User model + migration        (risk: low)
  2. Password hashing util         (risk: low)
  3. Auth service (hash+verify)    (risk: medium β€” unknown library choice)
  4. POST /login endpoint          (depends on 3)
  5. Session/token issuance        (depends on 3)
  6. Middleware to protect routes  (depends on 5)
  7. Tests for each of the above   (fan out after each leaf)
  8. Migration + rollback script   (depends on 1)
```

## 3. Writing a subtask spec (one line each)

Every leaf gets three fields β€” no more than one line each, or the decomposition is
itself over-engineered:

```
[objective]  one verb-phrase sentence of WHAT, not HOW
[accept]     the observable result that must hold
[verify]     the exact command that proves [accept]
```

Example:

```
Objective: Hash a plaintext password with a salted KDF.
Accept:    same input -> same stored hash; wrong input -> no match; never plaintext.
Verify:    pytest tests/test_password.py -k hash
```

## 4. Worked example: "add user auth" -> 8 leaves

| # | Leaf | Verify command |
|---|---|---|
| 1 | `User` model + migration | `alembic upgrade head && alembic check` |
| 2 | `hash_password` / `verify_password` util | `pytest tests/test_password.py` |
| 3 | Auth service `authenticate(email, pw)` | `pytest tests/test_auth_service.py` |
| 4 | `POST /login` endpoint | `pytest tests/test_login.py` |
| 5 | Session/token issuance + expiry | `pytest tests/test_token.py` |
| 6 | Auth middleware protecting routes | `pytest tests/test_middleware.py` |
| 7 | Down migration + rollback test | `alembic downgrade -1 && pytest` |
| 8 | README/API doc update | `git diff --stat README.md` |

Note leaf 7 β€” the rollback/migration leaf β€” is the one everyone forgets.

## 5. When to stop splitting

- Stop when each leaf is a **single commit's worth** of work (roughly 1 file /
  1–2 hours of focused change).
- Stop when further splitting produces **busywork** β€” leaves that are "write one
  line and run the formatter".
- A good check: each leaf maps to roughly one commit message subject line.

## 6. Common decomposition patterns

Most tasks decompose into one of a few shapes; recognizing the shape speeds up the
work and tells you which leaves are usually forgotten.

| Pattern | Leaves look like | Commonly forgotten leaf |
|---|---|---|
| **CRUD feature** | model β†’ schema/migration β†’ create/read/update/delete β†’ validation β†’ tests | permission/authorization |
| **Pipeline / ETL** | source β†’ transform stage 1..N β†’ sink β†’ error/retry β†’ tests | retry/dead-letter |
| **Migration** | write DDL β†’ backfill script β†’ dual-write β†’ cutover β†’ rollback | rollback |
| **Bug fix** | repro test β†’ root-cause isolate β†’ minimal fix β†’ regression test | the regression test |
| **Integration** | client wrapper β†’ error mapping β†’ config β†’ end-to-end test | error/edge mapping |

Naming the pattern first tells you which leaves are usually missing.

## 7. When NOT to decompose

- **Trivial one-line changes** β€” decomposing "fix a typo" is ceremony, not planning.
- **Exploratory work** β€” if you do not yet know the shape of the solution, a spike
  (see spike-prototype) is the right tool, not a decomposition.
- **You are the only consumer and it is under ~2 hours** β€” a short ordered list is
  enough; a full leaf tree with verify commands is overhead.

Decomposition is a tool for tasks too big to hold in your head, not a ritual to
apply to everything.

## Guardrails

- Do **not** decompose so finely that the plan itself takes longer to write than the
  work. Leaves of ~15–120 minutes of effort are the sweet spot.
- Do **not** mix unrelated concerns into one leaf ("add login AND fix the CSS on
  the navbar") β€” they review and verify differently.
- Do **not** leave a leaf with no verify command. A leaf without a check is a hope.
- Always include **migration, rollback, and doc** leaves for schema/API changes.
- Re-split, don't stretch, when a leaf turns out to be bigger than estimated.

## Pitfalls

- **Decomposing too fine** β€” 40 leaves of "rename this variable" is a ceremony, not a plan.
- **Mixing concerns** β€” "add the endpoint and write the tests and update the README"
  hides three separate risks in one line.
- **Forgetting the failure path** β€” decomposition that only covers the happy path
  collapses the first time an error branch is needed.
- **Ordering by preference, not risk** β€” doing the easy/fun leaves first and the
  hard/unknown ones last maximizes late rework.
- **Skipping rollback** β€” schema/API changes always need a "how do we undo this" leaf.

## Verify / Checklist

- [ ] Every leaf has a one-line objective, an acceptance result, and an exact verify command.
- [ ] No leaf requires "and then also…" to confirm it is done.
- [ ] Dependencies are drawn as a DAG and highest-risk leaves are scheduled first.
- [ ] Migration/rollback and documentation leaves are present for schema/API work.
- [ ] Each leaf is roughly one commit's worth of work.
- [ ] The whole plan is written down (markdown file, task tracker, or commit message) before coding starts.

Attached files

No attached files.