A Task List Isn't an Execution Plan
Why a list of tasks and an executable plan answer different questions, and when a plain list is still the right tool.
Software projects rarely lack a task list. Jira, a spreadsheet, a Markdown file, a whiteboard photo nobody can read a week later. What they often lack is an execution plan, and for a long time that works, because the plan lives in people’s heads. Someone just knows that the payment integration can’t start before the order model settles, and that “done” means the numbers were actually checked.
Agents make that gap visible. An agent doesn’t absorb the unwritten plan from the hallway. It gets what you give it, and a list of tasks is a surprisingly small thing to give.
What a list doesn’t say
A task list answers one question: what needs to happen? An execution plan has to answer several more:
- Order. What depends on what, and what can run in parallel?
- Inputs. What does this piece of work need to know before it starts: which decision, which contract, which files?
- Outputs. What does it produce that something else will consume?
- Done. What evidence says it’s finished, and who or what checks that evidence?
With people, most of this gets negotiated in conversation. With agents, it gets negotiated by whoever routes the work, which is usually me, copying context between sessions and trying to remember which branch was waiting on which. That’s the part I’m trying to make explicit.
The direction I’m experimenting with
The flow I’m exploring for my own projects looks like this:
product, journeys and screens → PRD → Tech Spec → execution graph → agent work → verification → integration
The first steps are ordinary product and architecture work, and they stay human decisions. The interesting step is the one in the middle: turning an approved spec into a graph where each node is a unit of work with its dependencies, the context it’s allowed to see, what it should produce, and the criteria it must meet.
Here is a conceptual example. It’s an illustration of the shape, not a file from a running system:
- id: order-status-api
depends_on: [order-model]
context: [tech-spec#orders, decisions/0007-status-names]
produces: [GET /orders/{id}/status]
done_when:
- contract tests pass
- status names match the decision record
- id: status-notifications
depends_on: [order-status-api]
context: [tech-spec#notifications]
produces: [notification on status change]
done_when:
- integration test covers the status → notification pathNothing clever is happening here. The point is that the relations, the boundaries and the definition of done live in something a tool can read, instead of in my memory. That’s what I mean by graph engineering in this context: making the relations and the state of execution explicit. The term gets used in other ways too. LangChain uses it for building agents as graphs of nodes and edges, and it isn’t a new discipline, GraphRAG, or a graph database.
Three graphs, three questions
One thing that kept confusing my own notes: there isn’t one graph. There are at least three, and they answer different questions.
- A feature graph asks: what does the product need, and which capabilities build on others?
- A project dependency graph asks: which parts of the codebase depend on which? Nx, for example, builds a project graph from the repository and a task graph when you run tasks, and uses them to work out what a change affects.
- An execution graph asks: what work happens next, with what context, and how do we know it’s done?
Mixing them produces plans that look rigorous and answer none of the questions well. A feature can touch five projects; a task can exist only to verify another task.
When not to use a graph
Honestly, most of the time.
If the work is three steps, one person, one afternoon, a checklist is the right tool. A graph has a cost: someone has to write it, keep it in sync with reality, and decide what happens when it’s wrong. If the plan changes every hour, a graph just becomes a very structured way to be out of date.
The places where I think it pays off are narrower:
- the work is split across several agents or sessions, and nobody holds the whole picture;
- the dependencies are real and expensive to get wrong;
- “done” needs evidence, not a checkbox.
I’m testing this on my own projects, and I don’t yet know where the line sits between useful structure and a second product to maintain. That’s the question I’ll keep writing about: when does a graph solve real coordination, and when is a plain list enough?
